Wordclock/webserver.lua

298 lines
11 KiB
Lua
Raw Normal View History

-- Webserver
local configFile="config.lua"
local httpSending=false
local sentBytes=0
2016-12-29 21:57:12 +01:00
function sendPage(conn, nameOfFile, replaceMap)
2017-01-03 13:48:24 +01:00
collectgarbage()
print("Sending " .. nameOfFile .. " " .. sentBytes .. "B already; " .. node.heap() .. "B in heap")
2016-12-29 21:01:15 +01:00
conn:on("sent", function(conn)
if (sentBytes == 0) then
conn:close()
print("Page sent")
2017-01-03 13:48:24 +01:00
collectgarbage()
2019-04-03 20:23:07 +02:00
httpSending=false
else
2019-04-03 20:23:07 +02:00
collectgarbage()
2016-12-29 21:57:12 +01:00
sendPage(conn, nameOfFile, replaceMap)
2016-12-29 21:01:15 +01:00
end
end)
2016-12-17 02:09:23 +01:00
2016-12-29 21:01:15 +01:00
if file.open(nameOfFile, "r") then
local buf=""
if (sentBytes <= 0) then
buf=buf .. "HTTP/1.1 200 OK\r\n"
buf=buf .. "Content-Type: text/html\r\n"
buf=buf .. "Connection: close\r\n"
buf=buf .. "Date: Thu, 29 Dec 2016 20:18:20 GMT\r\n"
buf=buf .. "\r\n\r\n"
end
2016-12-29 21:01:15 +01:00
-- amount of sent bytes is always zero at the beginning (so no problem)
file.seek("set", sentBytes)
local line = file.readline()
2016-12-29 21:57:12 +01:00
2016-12-17 02:09:23 +01:00
while (line ~= nil) do
2016-12-29 21:57:12 +01:00
-- all placeholder begin with a $, so search for it in the current line
if (line:find("$") ~= nil) then
-- Replace the placeholder with the dynamic content
if (replaceMap ~= nil) then
for key,value in pairs(replaceMap)
do
line = string.gsub(line, key, value)
end
end
end
2019-04-03 20:23:07 +02:00
-- increase the amount of sent bytes
sentBytes=sentBytes+string.len(line)
2016-12-17 02:09:23 +01:00
buf = buf .. line
2016-12-29 21:57:12 +01:00
2019-03-23 00:29:18 +01:00
-- Sent after 500 bytes data
if ( (string.len(buf) >= 500) or (node.heap() < 2000) ) then
2016-12-17 02:09:23 +01:00
line=nil
2016-12-29 21:01:15 +01:00
conn:send(buf)
print("Sent part of " .. sentBytes .. "B")
-- end the function, this part is sent
return
2016-12-17 02:09:23 +01:00
else
-- fetch the next line
2016-12-29 21:01:15 +01:00
line = file.readline()
2016-12-17 02:09:23 +01:00
end
end
2016-12-29 21:01:15 +01:00
--reset amount of sent bytes, as we reached the end
sentBytes=0
-- send the rest
if (string.len(buf) > 0) then
conn:send(buf)
print("Sent rest")
end
2016-12-17 02:09:23 +01:00
end
2016-12-29 23:20:40 +01:00
end
2016-12-17 02:09:23 +01:00
function fillDynamicMap()
2016-12-29 23:20:40 +01:00
replaceMap = {}
ssid, _ = wifi.sta.getconfig()
2021-02-05 20:58:15 +01:00
if (ssid == nil) then return replaceMap end
if (sntpserverhostname == nil) then sntpserverhostname="ptbtime1.ptb.de" end
if (timezoneoffset == nil) then timezoneoffset=1 end
2016-12-29 23:20:40 +01:00
-- Set the default color, if nothing is set
2021-02-05 20:58:15 +01:00
if (color == nil) then color=string.char(0,0,250) end
if (color1 == nil) then color1=color end
if (color2 == nil) then color2=color end
if (color3 == nil) then color3=color end
if (color4 == nil) then color4=color end
if (colorBg == nil) then colorBg=string.char(0,0,0) end
local hexColor = "#" .. string.format("%02x",string.byte(color,2)) .. string.format("%02x",string.byte(color,1)) .. string.format("%02x",string.byte(color,3))
local hexColor1 = "#" .. string.format("%02x",string.byte(color1,2)) .. string.format("%02x",string.byte(color1,1)) .. string.format("%02x",string.byte(color1,3))
local hexColor2 = "#" .. string.format("%02x",string.byte(color2,2)) .. string.format("%02x",string.byte(color2,1)) .. string.format("%02x",string.byte(color2,3))
local hexColor3 = "#" .. string.format("%02x",string.byte(color3,2)) .. string.format("%02x",string.byte(color3,1)) .. string.format("%02x",string.byte(color3,3))
local hexColor4 = "#" .. string.format("%02x",string.byte(color4,2)) .. string.format("%02x",string.byte(color4,1)) .. string.format("%02x",string.byte(color4,3))
local hexColorBg = "#" .. string.format("%02x",string.byte(colorBg,2)) .. string.format("%02x",string.byte(colorBg,1)) .. string.format("%02x",string.byte(colorBg,3))
2016-12-29 23:20:40 +01:00
replaceMap["$SSID"]=ssid
replaceMap["$SNTPSERVER"]=sntpserverhostname
replaceMap["$TIMEOFFSET"]=timezoneoffset
replaceMap["$THREEQUATER"]=(threequater and "checked" or "")
replaceMap["$ADDITIONAL_LINE"]=""
replaceMap["$HEXCOLORFG"]=hexColor
2016-12-29 23:20:40 +01:00
replaceMap["$HEXCOLOR1"]=hexColor1
replaceMap["$HEXCOLOR2"]=hexColor2
replaceMap["$HEXCOLOR3"]=hexColor3
replaceMap["$HEXCOLOR4"]=hexColor4
replaceMap["$HEXCOLORBG"]=hexColorBg
replaceMap["$INV46"]=((inv46 ~= nil and inv46 == "on") and "checked" or "")
replaceMap["$AUTODIM"]=((dim ~= nil and dim == "on") and "checked" or "")
2016-12-29 23:20:40 +01:00
return replaceMap
2016-12-17 02:09:23 +01:00
end
2022-12-09 22:19:27 +01:00
function readHex(source, variable)
local hexColor=string.sub(source, 4)
local red = tonumber(string.sub(hexColor, 1, 2), 16)
local green = tonumber(string.sub(hexColor, 3, 4), 16)
local blue = tonumber(string.sub(hexColor, 5, 6), 16)
file.write(variable.."=string.char(" .. green .. "," .. red .. "," .. blue .. ")\n")
end
2019-04-18 16:45:50 +02:00
function startWebServer()
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
conn:on("receive", function(conn,payload)
if (httpSending) then
print("HTTP sending... be patient!")
return
end
if (payload:find("GET /") ~= nil) then
httpSending=true
if (color == nil) then
color=string.char(0,128,0)
end
ws2812.write(string.char(0,0,0):rep(56) .. color:rep(2) .. string.char(0,0,0):rep(4) .. color:rep(2) .. string.char(0,0,0):rep(48))
2019-04-18 20:44:18 +02:00
if (sendPage ~= nil) then
print("Sending webpage.html (" .. tostring(node.heap()) .. "B free) ...")
-- Load the sendPagewebcontent
replaceMap=fillDynamicMap()
sendPage(conn, "webpage.html", replaceMap)
end
else if (payload:find("POST /") ~=nil) then
2016-12-29 23:20:40 +01:00
--code for handling the POST-request (updating settings)
_, postdatastart = payload:find("\r\n\r\n")
--Next lines catches POST-requests without POST-data....
if postdatastart==nil then postdatastart = 1 end
local postRequestData=string.sub(payload,postdatastart+1)
local _POST = {}
for i, j in string.gmatch(postRequestData, "(%w+)=([^&]+)&*") do
_POST[i] = j
end
--- Do the magic!
if (_POST.action ~= nil and _POST.action == "Reboot") then
node.restart()
2017-01-03 13:38:56 +01:00
return
2016-12-29 23:20:40 +01:00
end
if ((_POST.ssid~=nil) and (_POST.sntpserver~=nil) and (_POST.timezoneoffset~=nil)) then
print("New config!")
if (_POST.password==nil) then
_, password, _, _ = wifi.sta.getconfig()
print("Restoring password : " .. password)
_POST.password = password
password = nil
end
-- Safe configuration:
file.remove(configFile .. ".new")
sec, _ = rtctime.get()
file.open(configFile.. ".new", "w+")
2019-04-03 20:23:07 +02:00
file.write("-- Config\n" .. "station_cfg={}\nstation_cfg.ssid=\"" .. _POST.ssid .. "\"\nstation_cfg.pwd=\"" .. _POST.password .. "\"\nstation_cfg.save=false\nwifi.sta.config(station_cfg)\n")
file.write("sntpserverhostname=\"" .. _POST.sntpserver .. "\"\n" .. "timezoneoffset=\"" .. _POST.timezoneoffset .. "\"\n".. "inv46=\"" .. tostring(_POST.inv46) .. "\"\n" .. "dim=\"" .. tostring(_POST.dim) .. "\"\n")
2018-12-23 21:53:25 +01:00
2016-12-29 23:20:40 +01:00
if ( _POST.fcolor ~= nil) then
-- color=string.char(_POST.green, _POST.red, _POST.blue)
print ("Got fcolor: " .. _POST.fcolor)
2022-12-09 22:19:27 +01:00
readHex(_POST.fcolor, "color")
2016-12-29 23:20:40 +01:00
end
2022-12-09 22:19:27 +01:00
if ( _POST.mcolor1 ~= nil) then
readHex(_POST.mcolor1, "color1")
2016-12-29 23:20:40 +01:00
end
2022-12-09 22:19:27 +01:00
if ( _POST.mcolor2 ~= nil) then
readHex(_POST.mcolor2, "color2")
2016-12-29 23:20:40 +01:00
end
2022-12-09 22:19:27 +01:00
if ( _POST.mcolor3 ~= nil) then
readHex(_POST.mcolor3, "color3")
2016-12-29 23:20:40 +01:00
end
2022-12-09 22:19:27 +01:00
if ( _POST.mcolor4 ~= nil) then
readHex(_POST.mcolor4, "color4")
2016-12-29 23:20:40 +01:00
end
if ( _POST.bcolor ~= nil) then
local hexColor=string.sub(_POST.bcolor, 4)
2022-12-09 22:19:27 +01:00
readHex(_POST.bcolor, "colorBg")
end
2017-01-03 13:38:56 +01:00
if (getTime ~= nil) then
time = getTime(sec, timezoneoffset)
file.write("print(\"Config from " .. time.year .. "-" .. time.month .. "-" .. time.day .. " " .. time.hour .. ":" .. time.minute .. ":" .. time.second .. "\")\n")
end
2022-12-09 22:19:27 +01:00
if (_POST.web ~= nil) then
file.write("web=true\n")
-- fill the current values
web=true
else
file.write("web=nil\n") -- use webserver instead of mqtt or telnet
-- fill the current values
web=nil
end
2016-12-29 23:20:40 +01:00
if (_POST.threequater ~= nil) then
file.write("threequater=true\n")
-- fill the current values
threequater=true
2016-12-29 23:20:40 +01:00
else
file.write("threequater=nil\n") -- unset threequater
-- fill the current values
threequater=nil
2016-12-29 23:20:40 +01:00
end
file.close()
2016-12-30 14:23:34 +01:00
collectgarbage()
2016-12-29 23:20:40 +01:00
sec=nil
file.remove(configFile)
print("Rename config")
if (file.rename(configFile .. ".new", configFile)) then
print("Successfully")
2021-01-31 20:22:32 +01:00
local mytimer = tmr.create()
mytimer:register(50, tmr.ALARM_SINGLE, function (t)
replaceMap=fillDynamicMap()
replaceMap["$ADDITIONAL_LINE"]="<h2><font color=\"green\">New configuration saved</font></h2>"
print("Send success to client")
sendPage(conn, "webpage.html", replaceMap)
2021-01-31 20:22:32 +01:00
t:unregister()
end)
2021-01-31 20:22:32 +01:00
mytimer:start()
2016-12-29 23:20:40 +01:00
else
2021-01-31 20:22:32 +01:00
local mytimer = tmr.create()
mytimer:register(50, tmr.ALARM_SINGLE, function (t)
replaceMap=fillDynamicMap()
replaceMap["$ADDITIONAL_LINE"]="<h2><font color=\"red\">ERROR</font></h2>"
sendPage(conn, "webpage.html", replaceMap)
2021-01-31 20:22:32 +01:00
t:unregister()
end)
2021-01-31 20:22:32 +01:00
mytimer:start()
2016-12-29 23:20:40 +01:00
end
else
replaceMap=fillDynamicMap()
replaceMap["$ADDITIONAL_LINE"]="<h2><font color=\"orange\">Not all parameters set</font></h2>"
sendPage(conn, "webpage.html", replaceMap)
end
else
2016-06-19 17:48:39 +02:00
print("Hello via telnet")
--here is code, if the connection is not from a webbrowser, i.e. telnet or nc
global_c=conn
function s_output(str)
if(global_c~=nil)
then global_c:send(str)
end
end
node.output(s_output, 0)
global_c:on("receive",function(c,l)
node.input(l)
end)
global_c:on("disconnection",function(c)
node.output(nil)
global_c=nil
end)
2019-04-18 20:44:18 +02:00
print("Welcome to Word Clock")
end
end
end)
conn:on("disconnection", function(c)
print("Goodbye")
node.output(nil) -- un-register the redirect output function, output goes to serial
2019-04-03 21:08:27 +02:00
collectgarbage()
--reset amount of sent bytes, as we reached the end
sentBytes=0
end)
end)
end
2021-02-05 20:38:31 +01:00
-- start the webserver module
collectgarbage()
wifi.setmode(wifi.SOFTAP)
cfg={}
cfg.ssid="wordclock"
cfg.pwd="wordclock"
wifi.ap.config(cfg)
2021-02-05 20:38:31 +01:00
-- Write the buffer to the LEDs
local color=string.char(0,128,0)
local white=string.char(0,0,0)
local ledBuf= white:rep(6) .. color .. white:rep(7) .. color:rep(3) .. white:rep(44) .. color:rep(3) .. white:rep(50)
ws2812.write(ledBuf)
color=nil
white=nil
ledBuf=nil
print("Waiting in access point >wordclock< for Clients")
print("Please visit 192.168.4.1")
startWebServer()
2022-12-09 22:19:27 +01:00
collectgarbage()