Super bien avancé sur ma démo de chapeau

* ajouté un mini WEB IDE qui permet directement sur le NodeMCU d'éditer un script LUA
* refactorisé un poil mes deux WEB IDE
* rangé au bon endroit mes dexu WEB IDE
This commit is contained in:
Christian Zufferey
2018-12-05 21:19:44 +01:00
parent cb81ed2a22
commit 65fa2289ec
5 changed files with 571 additions and 36 deletions

View File

@@ -1,6 +1,6 @@
-- Scripts à charger après le boot pour démarrer son appli -- Scripts à charger après le boot pour démarrer son appli
print("\n boot.lua zf181205.2048 \n") print("\n boot.lua zf181205.2116 \n")
function heartbeat() function heartbeat()
f= "flash_led_xfois.lua" if file.exists(f) then dofile(f) end f= "flash_led_xfois.lua" if file.exists(f) then dofile(f) end
@@ -15,9 +15,9 @@ end
--f= "wifi_cli_conf.lua" if file.exists(f) then dofile(f) end --f= "wifi_cli_conf.lua" if file.exists(f) then dofile(f) end
--f= "wifi_cli_start.lua" if file.exists(f) then dofile(f) end --f= "wifi_cli_start.lua" if file.exists(f) then dofile(f) end
--f= "telnet_srv.lua" if file.exists(f) then dofile(f) end --f= "telnet_srv.lua" if file.exists(f) then dofile(f) end
--f= "web_ide2.lua" if file.exists(f) then dofile(f) end
f= "az_init_led.lua" if file.exists(f) then dofile(f) end
f= "wifi_cli_start.lua" if file.exists(f) then dofile(f) end f= "wifi_cli_start.lua" if file.exists(f) then dofile(f) end
f= "web_ide2.lua" if file.exists(f) then dofile(f) end
f= "az_init_led.lua" if file.exists(f) then dofile(f) end
f= "webleds.lua" if file.exists(f) then dofile(f) end f= "webleds.lua" if file.exists(f) then dofile(f) end
f= "a_train3.lua" if file.exists(f) then dofile(f) end f= "a_train3.lua" if file.exists(f) then dofile(f) end

View File

@@ -0,0 +1,158 @@
-- Petit WEB IDE tout simple autonome
-- ATTENTION: tourne sur le port 88 !
print("\n _web_ide2.lua zf181205.2112 \n")
--[[
XChip's NodeMCU IDE
Create, Edit and run NodeMCU files using your webbrowser.
Examples:
http://<mcu_ip>/ will list all the files in the MCU
http://<mcu_ip>/newfile.lua displays the file on your browser
http://<mcu_ip>/newfile.lua?edit allows to creates or edits the specified script in your browser
http://<mcu_ip>/newfile.lua?run it will run the specified script and will show the returned value
]]--
srv=net.createServer(net.TCP)
srv:listen(88,function(conn)
local rnrn=0
local Status = 0
local DataToGet = 0
local method=""
local url=""
local vars=""
conn:on("receive",function(conn,payload)
if Status==0 then
_, _, method, url, vars = string.find(payload, "([A-Z]+) /([^?]*)%??(.*) HTTP")
print(method, url, vars)
end
if method=="POST" then
if Status==0 then
--print("status", Status)
_,_,DataToGet, payload = string.find(payload, "Content%-Length: (%d+)(.+)")
if DataToGet~=nil then
DataToGet = tonumber(DataToGet)
--print(DataToGet)
rnrn=1
Status = 1
else
print("bad length")
end
end
-- find /r/n/r/n
if Status==1 then
--print("status", Status)
local payloadlen = string.len(payload)
local mark = "\r\n\r\n"
local i
for i=1, payloadlen do
if string.byte(mark, rnrn) == string.byte(payload, i) then
rnrn=rnrn+1
if rnrn==5 then
payload = string.sub(payload, i+1,payloadlen)
file.open(url, "w")
file.close()
Status=2
break
end
else
rnrn=1
end
end
if Status==1 then
return
end
end
if Status==2 then
--print("status", Status)
if payload~=nil then
DataToGet=DataToGet-string.len(payload)
--print("DataToGet:", DataToGet, "payload len:", string.len(payload))
file.open(url, "a+")
file.write(payload)
file.close()
else
conn:send("HTTP/1.1 200 OK\r\n\r\nERROR")
Status=0
end
if DataToGet==0 then
conn:send("HTTP/1.1 200 OK\r\n\r\nOK")
Status=0
end
end
return
end
DataToGet = -1
if url == "favicon.ico" then
conn:send("HTTP/1.1 404 file not found")
return
end
conn:send("HTTP/1.1 200 OK\r\n\r\n")
-- it wants a file in particular
if url~="" and vars=="" then
DataToGet = 0
return
end
conn:send("<html><body><h1>NodeMCU IDE</h1>")
if vars=="edit" then
conn:send("<script>function tag(c){document.getElementsByTagName('w')[0].innerHTML=c};\n")
conn:send("var x=new XMLHttpRequest()\nx.onreadystatechange=function(){if(x.readyState==4) document.getElementsByName('t')[0].value = x.responseText; };\nx.open('GET',location.pathname,true)\nx.send()</script>")
conn:send("<a href='/'>Back to file list</a><br><br><textarea name=t cols=79 rows=17></textarea></br>")
conn:send("<button onclick=\"tag('Saving');x.open('POST',location.pathname,true);\nx.onreadystatechange=function(){if(x.readyState==4) tag(x.responseText);};\nx.send(new Blob([document.getElementsByName('t')[0].value],{type:'text/plain'}));\">Save</button><a href='?run'>run</a><w></w>")
end
if vars=="run" then
conn:send("<verbatim>")
local st, result=pcall(dofile, url)
conn:send(tostring(result))
conn:send("</verbatim>")
end
if url=="" then
local l = file.list();
for k,v in pairs(l) do
conn:send("<a href='"..k.."?edit'>"..k.."</a>, size:"..v.."<br>")
end
end
conn:send("</body></html>")
end)
conn:on("sent",function(conn)
if DataToGet>=0 and method=="GET" then
if file.open(url, "r") then
file.seek("set", DataToGet)
local line=file.read(512)
file.close()
if line then
conn:send(line)
DataToGet = DataToGet + 512
if (string.len(line)==512) then
return
end
end
end
end
conn:close()
end)
end)
print("listening, free:", node.heap())

View File

@@ -1,7 +1,7 @@
-- Petit script de serveur WEB pour piloter les effets des LED RGB -- Petit script de serveur WEB pour piloter les effets des LED RGB
-- source: https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/webap_toggle_pin.lua -- source: https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/webap_toggle_pin.lua
print("\n webleds.lua zf181205.2048 \n") print("\n webleds.lua zf181205.2101 \n")
-- send a file from memory to the client; max. line length = 1024 bytes! -- send a file from memory to the client; max. line length = 1024 bytes!
@@ -22,9 +22,6 @@ srv = net.createServer(net.TCP)
srv:listen(80, function(conn) srv:listen(80, function(conn)
conn:on("receive", function(client, request) conn:on("receive", function(client, request)
local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP") local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP")
if not string.find(request, "/favicon.ico") then if not string.find(request, "/favicon.ico") then
--print("coucou") --print("coucou")
if (method == nil) then if (method == nil) then
@@ -76,35 +73,7 @@ srv:listen(80, function(conn)
print("send html...") print("send html...")
send_file(client, 'index.html') send_file(client, 'index.html')
end end
--[[
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+)=([a-z0-9_]+)&*") do
_GET[k] = v
end
end
if (_GET.set == "effect") then
print("setting effect", _GET.effect)
ws2812_effects.set_mode(_GET.effect)
ws2812_effects.set_speed(200)
ws2812_effects.set_brightness(50)
ws2812_effects.start()
end
if (_GET.set == "color") then
print("setting color (RGB)", _GET.r, _GET.g, _GET.b)
ws2812_effects.set_color(_GET.g, _GET.r, _GET.b) -- obviously our strip is GRB and not RGB
end
send_file(client, 'index.html')
--]]
end) end)
conn:on("sent", function(c) c:close() end) conn:on("sent", function(c) c:close() end)
end) end)

250
WebIDE/web_ide1.lua Normal file
View File

@@ -0,0 +1,250 @@
-- Petit WEB IDE tout simple
-- ATTENTION: tourne sur le port 88 !
print("\n _web_ide1.lua zf181205.2112 \n")
--[[
XChip's NodeMCU IDE
Original Source: http://www.esp8266.com/viewtopic.php?f=19&t=1549
Petr Stehlik found the source in October 2016 and gave it a new home
at https://github.com/joysfera/nodemcu-web-ide under the GPL license.
Then updated it for new async socket send(), fixed, cleaned up,
added external editor with syntax highlighting and further improves it.
Create, Edit and run NodeMCU files using your web browser.
Examples:
http://<mcu_ip>/ will list all the files in the MCU
http://<mcu_ip>/newfile.lua displays the file on your browser
http://<mcu_ip>/newfile.lua?edit allows to creates or edits the specified script in your browser
http://<mcu_ip>/newfile.lua?run it will run the specified script and will show the returned value
--]]
local function editor(aceEnabled) -- feel free to disable the shiny Ajax.org Cloud Editor
local AceEnabled = aceEnabled == nil and true or aceEnabled
srv = net.createServer(net.TCP)
srv:listen(88, function(conn)
local rnrn = 0
local Status = 0
local DataToGet = 0
local method = ""
local url = ""
local vars = ""
conn:on("receive", function(sck, payload)
if Status == 0 then
_, _, method, url, vars = string.find(payload, "([A-Z]+) /([^?]*)%??(.*) HTTP")
-- print("Method, URL, vars: ", method, url, vars)
end
if method == "POST" then
if Status == 0 then
-- print("status", Status)
_, _, DataToGet, payload = string.find(payload, "Content%-Length: (%d+)(.+)")
if DataToGet then
DataToGet = tonumber(DataToGet)
-- print("DataToGet = "..DataToGet)
rnrn = 1
Status = 1
else
print("bad length")
end
end
-- find /r/n/r/n
if Status == 1 then
-- print("status", Status)
local payloadlen = string.len(payload)
local mark = "\r\n\r\n"
local i
for i=1, payloadlen do
if string.byte(mark, rnrn) == string.byte(payload, i) then
rnrn = rnrn + 1
if rnrn == 5 then
payload = string.sub(payload, i+1, payloadlen)
file.open(url, "w")
file.close()
Status = 2
break
end
else
rnrn = 1
end
end
if Status == 1 then
return
end
end
if Status == 2 then
-- print("status", Status)
if payload then
DataToGet = DataToGet - string.len(payload)
--print("DataToGet:", DataToGet, "payload len:", string.len(payload))
file.open(url, "a+")
file.write(payload)
file.close()
else
sck:send("HTTP/1.1 200 OK\r\n\r\nERROR")
Status = 0
end
if DataToGet == 0 then
sck:send("HTTP/1.1 200 OK\r\n\r\nOK")
Status = 0
end
end
return
end
-- end of POST method handling
DataToGet = -1
if url == "favicon.ico" then
-- print("favicon.ico handler sends 404")
sck:send("HTTP/1.1 404 file not found")
return
end
local sen = "HTTP/1.1 200 OK\r\n\r\n"
-- it wants a file in particular
if url ~= "" and vars == "" then
DataToGet = 0
sck:send(sen)
return
end
sen = sen .. "<html><body><h1><a href='/'>NodeMCU IDE</a></h1>"
if vars == "edit" then
if AceEnabled then
local mode = 'ace/mode/'
if url:match(".css") then mode = mode .. 'css'
elseif url:match(".html") then mode = mode .. 'html'
elseif url:match(".json") then mode = mode .. 'json'
elseif url:match(".js") then mode = mode .. 'javascript'
else mode = mode .. 'lua'
end
sen = sen .. "<style type='text/css'>#editor{width: 100%; height: 80%}</style><div id='editor'></div><script src='//rawgit.com/ajaxorg/ace-builds/master/src-min-noconflict/ace.js'></script>"
.. "<script>var e=ace.edit('editor');e.setTheme('ace/theme/monokai');e.getSession().setMode('"..mode.."');function getSource(){return e.getValue();};function setSource(s){e.setValue(s);}</script>"
else
sen = sen .. "<textarea name=t cols=79 rows=17></textarea></br>"
.. "<script>function getSource() {return document.getElementsByName('t')[0].value;};function setSource(s) {document.getElementsByName('t')[0].value = s;};</script>"
end
sen = sen .. "<script>function tag(c){document.getElementsByTagName('w')[0].innerHTML=c};var x=new XMLHttpRequest();x.onreadystatechange=function(){if(x.readyState==4) setSource(x.responseText);};"
.. "x.open('GET',location.pathname);x.send()</script><button onclick=\"tag('Saving, wait!');x.open('POST',location.pathname);x.onreadystatechange=function(){console.log(x.readyState);"
.. "if(x.readyState==4) tag(x.responseText);};x.send(new Blob([getSource()],{type:'text/plain'}));\">Save</button> <a href='?run'>run</a> <w></w>"
elseif vars == "run" then
sen = sen .. "<verbatim>"
function s_output(str) sen = sen .. str end
node.output(s_output, 0) -- re-direct output to function s_output.
local st, result = pcall(dofile, url)
-- delay the output capture by 1000 milliseconds to give some time to the user routine in pcall()
tmr.alarm(0, 1000, tmr.ALARM_SINGLE, function()
node.output(nil)
if result then
local outp = tostring(result):sub(1,1300) -- to fit in one send() packet
result = nil
sen = sen .. "<br>Result of the run: " .. outp .. "<br>"
end
sen = sen .. "</verbatim></body></html>"
sck:send(sen)
end)
return
elseif vars == "compile" then
collectgarbage()
node.compile(url)
url = ""
elseif vars == "delete" then
file.remove(url)
url = ""
elseif vars == "restart" then
node.restart()
return
end
local message = {}
message[#message + 1] = sen
sen = nil
if url == "" then
local l = file.list();
message[#message + 1] = "<table border=1 cellpadding=3><tr><th>Name</th><th>Size</th><th>Edit</th><th>Compile</th><th>Delete</th></tr>"
for k,v in pairs(l) do
local line = "<tr><td><a href='" ..k.. "'>" ..k.. "</a></td><td>" ..v.. "</td><td>"
local editable = k:sub(-4, -1) == ".lua" or k:sub(-4, -1) == ".css" or k:sub(-5, -1) == ".html" or k:sub(-5, -1) == ".json"
if editable then
line = line .. "<a href='" ..k.. "?edit'>edit</a>"
end
line = line .. "</td><td>"
if k:sub(-4, -1) == ".lua" then
line = line .. "<a href='" ..k.. "?compile'>compile</a>"
end
line = line .. "</td><td><a href='" ..k.. "?delete'>delete</a></td></tr>"
message[#message + 1] = line
end
message[#message + 1] = "</table><a href='#' onclick='v=prompt(\"Filename\");if (v!=null) { this.href=\"/\"+v+\"?edit\"; return true;} else return false;'>Create new</a> &nbsp; &nbsp; "
message[#message + 1] = "<a href='#' onclick='var x=new XMLHttpRequest();x.open(\"GET\",\"/?restart\");x.send();setTimeout(function(){location.href=\"/\"},5000);this.innerText=\"Please wait\";return false'>Restart</a>"
end
message[#message + 1] = "</body></html>"
local function send_table(sk)
if #message > 0 then
sk:send(table.remove(message, 1))
else
sk:close()
message = nil
end
end
sck:on("sent", send_table)
send_table(sck)
end)
conn:on("sent", function(sck)
if DataToGet >= 0 and method == "GET" then
if file.open(url, "r") then
file.seek("set", DataToGet)
local chunkSize = 512
local line = file.read(chunkSize)
file.close()
if line then
sck:send(line)
DataToGet = DataToGet + chunkSize
if string.len(line) == chunkSize then return end
end
end
end
sck:close()
sck = nil
end)
end)
end
--[[if wifi.sta.status() == wifi.STA_GOTIP then
print("http://"..wifi.sta.getip().."/")
editor()
else
print("WiFi connecting...")
wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function()
wifi.eventmon.unregister(wifi.eventmon.STA_GOT_IP)
print("http://"..wifi.sta.getip().."/")
editor()
end)
end
]]
editor()

158
WebIDE/web_ide2.lua Normal file
View File

@@ -0,0 +1,158 @@
-- Petit WEB IDE tout simple autonome
-- ATTENTION: tourne sur le port 88 !
print("\n _web_ide2.lua zf181205.2112 \n")
--[[
XChip's NodeMCU IDE
Create, Edit and run NodeMCU files using your webbrowser.
Examples:
http://<mcu_ip>/ will list all the files in the MCU
http://<mcu_ip>/newfile.lua displays the file on your browser
http://<mcu_ip>/newfile.lua?edit allows to creates or edits the specified script in your browser
http://<mcu_ip>/newfile.lua?run it will run the specified script and will show the returned value
]]--
srv=net.createServer(net.TCP)
srv:listen(88,function(conn)
local rnrn=0
local Status = 0
local DataToGet = 0
local method=""
local url=""
local vars=""
conn:on("receive",function(conn,payload)
if Status==0 then
_, _, method, url, vars = string.find(payload, "([A-Z]+) /([^?]*)%??(.*) HTTP")
print(method, url, vars)
end
if method=="POST" then
if Status==0 then
--print("status", Status)
_,_,DataToGet, payload = string.find(payload, "Content%-Length: (%d+)(.+)")
if DataToGet~=nil then
DataToGet = tonumber(DataToGet)
--print(DataToGet)
rnrn=1
Status = 1
else
print("bad length")
end
end
-- find /r/n/r/n
if Status==1 then
--print("status", Status)
local payloadlen = string.len(payload)
local mark = "\r\n\r\n"
local i
for i=1, payloadlen do
if string.byte(mark, rnrn) == string.byte(payload, i) then
rnrn=rnrn+1
if rnrn==5 then
payload = string.sub(payload, i+1,payloadlen)
file.open(url, "w")
file.close()
Status=2
break
end
else
rnrn=1
end
end
if Status==1 then
return
end
end
if Status==2 then
--print("status", Status)
if payload~=nil then
DataToGet=DataToGet-string.len(payload)
--print("DataToGet:", DataToGet, "payload len:", string.len(payload))
file.open(url, "a+")
file.write(payload)
file.close()
else
conn:send("HTTP/1.1 200 OK\r\n\r\nERROR")
Status=0
end
if DataToGet==0 then
conn:send("HTTP/1.1 200 OK\r\n\r\nOK")
Status=0
end
end
return
end
DataToGet = -1
if url == "favicon.ico" then
conn:send("HTTP/1.1 404 file not found")
return
end
conn:send("HTTP/1.1 200 OK\r\n\r\n")
-- it wants a file in particular
if url~="" and vars=="" then
DataToGet = 0
return
end
conn:send("<html><body><h1>NodeMCU IDE</h1>")
if vars=="edit" then
conn:send("<script>function tag(c){document.getElementsByTagName('w')[0].innerHTML=c};\n")
conn:send("var x=new XMLHttpRequest()\nx.onreadystatechange=function(){if(x.readyState==4) document.getElementsByName('t')[0].value = x.responseText; };\nx.open('GET',location.pathname,true)\nx.send()</script>")
conn:send("<a href='/'>Back to file list</a><br><br><textarea name=t cols=79 rows=17></textarea></br>")
conn:send("<button onclick=\"tag('Saving');x.open('POST',location.pathname,true);\nx.onreadystatechange=function(){if(x.readyState==4) tag(x.responseText);};\nx.send(new Blob([document.getElementsByName('t')[0].value],{type:'text/plain'}));\">Save</button><a href='?run'>run</a><w></w>")
end
if vars=="run" then
conn:send("<verbatim>")
local st, result=pcall(dofile, url)
conn:send(tostring(result))
conn:send("</verbatim>")
end
if url=="" then
local l = file.list();
for k,v in pairs(l) do
conn:send("<a href='"..k.."?edit'>"..k.."</a>, size:"..v.."<br>")
end
end
conn:send("</body></html>")
end)
conn:on("sent",function(conn)
if DataToGet>=0 and method=="GET" then
if file.open(url, "r") then
file.seek("set", DataToGet)
local line=file.read(512)
file.close()
if line then
conn:send(line)
DataToGet = DataToGet + 512
if (string.len(line)==512) then
return
end
end
end
end
conn:close()
end)
end)
print("listening, free:", node.heap())