├── mcunode ├── conf │ └── app.conf ├── controllers │ ├── term.go │ ├── default.go │ ├── websocket.go │ ├── proxy.go │ └── mcuserver.go ├── static │ ├── css │ │ ├── common.css │ │ ├── style.css │ │ ├── neat.css │ │ ├── codemirror.css │ │ └── xterm.css │ └── js │ │ ├── lua.min.js │ │ ├── matchbrackets.js │ │ ├── mcunode.js │ │ └── bootstrap.min.js ├── routers │ └── router.go ├── main.go ├── models │ └── archive.go ├── build.bat ├── build.sh └── views │ ├── terminal.html │ └── index.html ├── NODEMCU Lua Demo(template file included) ├── WebProxyDemo │ ├── 简版远程LED控制 │ │ ├── readme.txt │ │ ├── 截图.png │ │ ├── indextpl.html │ │ ├── init.lua │ │ └── mcunode.lua │ ├── README.md │ └── LEDremote │ │ ├── 截图.png │ │ ├── README.md │ │ ├── indextpl.html │ │ ├── init.lua │ │ └── mcunode.lua ├── OnLineTerminalAndOTG │ ├── README.md │ └── init.lua ├── nodemcu_code_lib and demo │ ├── README.md │ ├── indextpl.html │ ├── init.lua │ └── mcunode.lua └── README.md ├── imgs ├── download.png ├── mcunode.png ├── webProxy.png └── ledRemote.png ├── .idea ├── vcs.xml └── encodings.xml ├── LICENSE └── README.md /mcunode/conf/app.conf: -------------------------------------------------------------------------------- 1 | httpport = 80 2 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/简版远程LED控制/readme.txt: -------------------------------------------------------------------------------- 1 | init.lua -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/README.md: -------------------------------------------------------------------------------- 1 | ## 本文件夹的含多个mcunode网页代理实例 2 | -------------------------------------------------------------------------------- /imgs/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTServ/McuNode-server/HEAD/imgs/download.png -------------------------------------------------------------------------------- /imgs/mcunode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTServ/McuNode-server/HEAD/imgs/mcunode.png -------------------------------------------------------------------------------- /imgs/webProxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTServ/McuNode-server/HEAD/imgs/webProxy.png -------------------------------------------------------------------------------- /imgs/ledRemote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTServ/McuNode-server/HEAD/imgs/ledRemote.png -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/OnLineTerminalAndOTG/README.md: -------------------------------------------------------------------------------- 1 | #### 不使用库的远程IDE nodemcu端,需要配置id和wifi信息 2 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/nodemcu_code_lib and demo/README.md: -------------------------------------------------------------------------------- 1 | ### mcunode.lua库的简单使用,可以远程IDE,远程网页代理(简单) 2 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/LEDremote/截图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTServ/McuNode-server/HEAD/NODEMCU Lua Demo(template file included)/WebProxyDemo/LEDremote/截图.png -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/简版远程LED控制/截图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IoTServ/McuNode-server/HEAD/NODEMCU Lua Demo(template file included)/WebProxyDemo/简版远程LED控制/截图.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/nodemcu_code_lib and demo/indextpl.html: -------------------------------------------------------------------------------- 1 |

HELLO Farry

2 | {{name}}:{{work}} 3 |

HELLO Farry

4 |

HELLO Farry

5 |

HELLO Farry

6 |

HELLO Farry

7 |

HELLO Farry

8 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/LEDremote/README.md: -------------------------------------------------------------------------------- 1 | 需要配置init.lua最后一行的id,服务器ip或域名,wifi名与密码 2 | 3 | ![image](https://github.com/IoTServ/McuNode-server/blob/master/NODEMCU%20Lua%20Demo(template%20file%20included)/WebProxyDemo/LEDremote/%E6%88%AA%E5%9B%BE.png?raw=true) 4 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/README.md: -------------------------------------------------------------------------------- 1 | # A online Terminal And a Web Proxy Demo 2 | 3 | ###  包含的项目: 4 | ##### OnLineTerminalAndOTG  --在线IDE(不使用mcunode.lua库版本) 5 | ##### WebProxyDemo/LEDremote   --互联网访问nodemcu网页控制LED实例(含在线IDE,在线文件升级,使用mcunode.lua库) 6 | ##### nodemcu_code_lib and demo --简单网页代理功能,复杂功能看WebProxyDemo/LEDremote 7 | -------------------------------------------------------------------------------- /mcunode/controllers/term.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | _"strings" 6 | ) 7 | 8 | type TermController struct { 9 | beego.Controller 10 | } 11 | 12 | func (c *TermController) Get() { 13 | id := c.Ctx.Input.Param(":id") 14 | 15 | c.Data["id"] = id 16 | c.TplName = "terminal.html" 17 | } 18 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/简版远程LED控制/indextpl.html: -------------------------------------------------------------------------------- 1 |

ESP8266 Web Server

2 |

GPIO0

3 |

GPIO2

4 |

Raw Data To MCU:{{raw}}


-------------------------------------------------------------------------------- /mcunode/controllers/default.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | ) 6 | 7 | type MainController struct { 8 | beego.Controller 9 | } 10 | 11 | func (c *MainController) Get() { 12 | c.TplName = "index.html" 13 | 14 | //data, err := Asset("views/index.html") 15 | //if err != nil { 16 | // // Asset was not found. 17 | //} 18 | //c.Ctx.WriteString(string(data)) 19 | } 20 | -------------------------------------------------------------------------------- /mcunode/static/css/common.css: -------------------------------------------------------------------------------- 1 | .footer { 2 | background: #474E5D; 3 | padding: 15px 0 5px; 4 | font-size: 13px; 5 | } 6 | .footer-content { 7 | text-align: center; 8 | color: #8a6d3b; 9 | } 10 | .footer-content a { 11 | text-decoration: none; 12 | color: #8a6d3b; 13 | } 14 | .code { 15 | width: 600px; 16 | height: 640px; 17 | } 18 | .code2 { 19 | width: 600px; 20 | height: 210px; 21 | } 22 | span { 23 | font-size: large; 24 | color: red; 25 | } -------------------------------------------------------------------------------- /mcunode/static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 60px; 3 | padding-bottom: 40px; 4 | } 5 | 6 | .terminal { 7 | border: #000 solid 5px; 8 | font-family: "Monaco", "DejaVu Sans Mono", "Liberation Mono", monospace; 9 | font-size: 11px; 10 | color: #f0f0f0; 11 | background: #000; 12 | width: 600px; 13 | box-shadow: rgba(0, 0, 0, 0.8) 2px 2px 20px; 14 | } 15 | 16 | .reverse-video { 17 | color: #000; 18 | background: #f0f0f0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /mcunode/routers/router.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | "github.com/IoTServ/McuNode-server/mcunode/controllers" 5 | "github.com/astaxie/beego" 6 | ) 7 | 8 | func init() { 9 | beego.Router("/", &controllers.MainController{}) 10 | beego.Router("/term/:id:string", &controllers.TermController{}) 11 | beego.Router("/ws/:id:string", &controllers.WebSocketController{}, "get:Join") 12 | beego.Router("/proxy/:id:string/*", &controllers.ProxyController{}) 13 | //beego.Router("/*", &controllers.StaticController{}) 14 | } 15 | -------------------------------------------------------------------------------- /mcunode/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "github.com/IoTServ/McuNode-server/mcunode/routers" 5 | "github.com/astaxie/beego" 6 | "fmt" 7 | ) 8 | 9 | func main() { 10 | beego.BConfig.AppName = "McuNode" 11 | beego.BConfig.Listen.HTTPPort=80 12 | beego.BConfig.RunMode="prod" 13 | beego.BConfig.ServerName = "McuNode Server" 14 | beego.BConfig.EnableErrorsShow = false 15 | beego.BConfig.EnableErrorsRender=false 16 | beego.BConfig.WebConfig.FlashName = "MCUNODE_FLASH" 17 | beego.BConfig.WebConfig.Session.SessionName = "MCUNODEsessionID" 18 | beego.Run() 19 | fmt.Printf("Please open this web server port : 80") 20 | } 21 | -------------------------------------------------------------------------------- /mcunode/static/css/neat.css: -------------------------------------------------------------------------------- 1 | .cm-s-neat span.cm-comment { color: #a86; } 2 | .cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; } 3 | .cm-s-neat span.cm-string { color: #a22; } 4 | .cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; } 5 | .cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; } 6 | .cm-s-neat span.cm-variable { color: black; } 7 | .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; } 8 | .cm-s-neat span.cm-meta { color: #555; } 9 | .cm-s-neat span.cm-link { color: #3a3; } 10 | 11 | .cm-s-neat .CodeMirror-activeline-background { background: #e8f2ff; } 12 | .cm-s-neat .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; } 13 | -------------------------------------------------------------------------------- /mcunode/models/archive.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | _"github.com/astaxie/beego/orm" 5 | _"time" 6 | ) 7 | 8 | type Event struct { 9 | User string 10 | Content []byte 11 | } 12 | 13 | 14 | // Model Struct 15 | //type DEVICE struct { 16 | // Id int 17 | // MCUID string `orm:"index"` 18 | // DATA string `orm:"size(10240)"` 19 | // DATE time.Time 20 | //} 21 | // 22 | //func init() { 23 | // // set default database 24 | // orm.RegisterDataBase("default", "mysql", "root:root@/mcunode?charset=utf8", 30) 25 | // 26 | // // register model 27 | // orm.RegisterModel(new(DEVICE)) 28 | // 29 | // // create table 30 | // orm.RunSyncdb("default", false, true) 31 | // 32 | // //o := orm.NewOrm() 33 | // // 34 | // //user := DEVICE{MCUID: "slene",DATA:"wode",DATE:time.Now()} 35 | // // 36 | // //// insert 37 | // //id, _ := o.Insert(&user) 38 | // //fmt.Printf(string(id)) 39 | //} -------------------------------------------------------------------------------- /mcunode/controllers/websocket.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/astaxie/beego" 7 | "github.com/gorilla/websocket" 8 | _"fmt" 9 | ) 10 | 11 | // WebSocketController handles WebSocket requests. 12 | type WebSocketController struct { 13 | beego.Controller 14 | } 15 | 16 | // Join method handles WebSocket requests for WebSocketController. 17 | func (this *WebSocketController) Join() { 18 | uname := this.Ctx.Input.Param(":id") 19 | if len(uname) == 0 { 20 | this.Redirect("/", 302) 21 | return 22 | } 23 | 24 | // Upgrade from http request to WebSocket. 25 | ws, err := websocket.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request, nil, 1024, 1024) 26 | if _, ok := err.(websocket.HandshakeError); ok { 27 | http.Error(this.Ctx.ResponseWriter, "Not a websocket handshake", 400) 28 | return 29 | } else if err != nil { 30 | beego.Error("Cannot setup WebSocket connection:", err) 31 | return 32 | } 33 | 34 | 35 | Join(uname, ws) 36 | 37 | this.Ctx.WriteString("ok") 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 iotserv 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/nodemcu_code_lib and demo/init.lua: -------------------------------------------------------------------------------- 1 | local mcunode = require "mcunode" 2 | 3 | --url:http://mcunodeserver-ip/proxy//gpio?pin=1&val=0 4 | --return:status=success 5 | mcunode.handle("/gpio",function(req,res) 6 | local pin = req.getParam("pin") 7 | local val = req.getParam("val") 8 | if( pin ~= nil) and (val ~= nil) then 9 | print("pin: "..pin .." , val: " ..val) 10 | gpio.mode(pin, gpio.OUTPUT) 11 | gpio.write(pin, val) 12 | res.setAttribute("status","success") 13 | end 14 | return res 15 | end) 16 | mcunode.handle("/test",function(req,res) 17 | local name = req.getParam("name") 18 | res.setAttribute("name",name) 19 | res.body="wodename:{{name}}" 20 | return res 21 | end) 22 | --url:http://mcunodeserver-ip/proxy//index.html?name=farry&work=student 23 | mcunode.handle("/index.html",function(req,res) 24 | local name = req.getParam("name") 25 | res.setAttribute("name",name) 26 | local work = req.getParam("work") 27 | res.setAttribute("work",work) 28 | res.file = "indextpl.html" -- ...

{{name}}

... 29 | return res 30 | end) 31 | mcunode.connect("","","","") -------------------------------------------------------------------------------- /mcunode/build.bat: -------------------------------------------------------------------------------- 1 | set CGO_ENABLED=0 2 | set GOROOT_BOOTSTRAP=C:/Go 3 | ::x86块 4 | set GOARCH=386 5 | set GOOS=windows 6 | go build main.go 7 | ren main.exe windows386.exe 8 | set GOOS=linux 9 | go build main.go 10 | ren main linux386 11 | set GOOS=freebsd 12 | go build main.go 13 | ren main freebsd386 14 | set GOOS=darwin 15 | go build main.go 16 | ren main darwin386 17 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 18 | 19 | ::x64块 20 | set GOARCH=amd64 21 | set GOOS=windows 22 | go build main.go 23 | ren main.exe windowsAmd64.exe 24 | set GOOS=linux 25 | go build main.go 26 | ren main linuxAMD64 27 | set GOOS=freebsd 28 | go build main.go 29 | ren main freebsdAMD64 30 | set GOOS=darwin 31 | go build main.go 32 | ren main darwinAMD64 33 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 34 | 35 | ::arm块 36 | set GOARCH=arm 37 | set GOOS=linux 38 | go build main.go 39 | ren main LinuxArm 40 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 41 | 42 | ::mips块 43 | set GOARCH=mips64le 44 | set GOOS=linux 45 | go build main.go 46 | ren main LinuxMips64le 47 | 48 | set GOARCH=mips64 49 | set GOOS=linux 50 | go build main.go 51 | ren main LinuxMips64 52 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 53 | set GOARCH=amd64 54 | set GOOS=windows 55 | pause -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/简版远程LED控制/init.lua: -------------------------------------------------------------------------------- 1 | local mcunode = require "mcunode" 2 | 3 | --url:http://mcunodeserver-ip/proxy//gpio?pin=1&val=0 4 | --return:status=success 5 | mcunode.handle("/gpio",function(req,res) 6 | local pin = req.getParam("pin") 7 | local val = req.getParam("val") 8 | if( pin ~= nil) and (val ~= nil) then 9 | print("pin: "..pin .." , val: " ..val) 10 | gpio.mode(pin, gpio.OUTPUT) 11 | gpio.write(pin, val) 12 | res.setAttribute("status","success") 13 | end 14 | return res 15 | end) 16 | mcunode.handle("/test",function(req,res) 17 | local name = req.getParam("name") 18 | res.setAttribute("name",name) 19 | res.body="wodename:{{name}}" 20 | return res 21 | end) 22 | --url:http://mcunodeserver-ip/proxy//index.html?name=farry&work=student 23 | mcunode.handle("/index.html",function(req,res) 24 | res.file = "indextpl.html" 25 | local pin = req.getParam("pin") 26 | res.setAttribute("raw",pin) 27 | gpio.mode(0, gpio.OUTPUT) 28 | gpio.mode(2, gpio.OUTPUT) 29 | if( pin == "ON1") then 30 | gpio.write(0,0) 31 | elseif(pin == "ON2" ) then 32 | gpio.write(2,0) 33 | elseif(pin == "OFF1" ) then 34 | gpio.write(0,1) 35 | elseif(pin == "OFF2" ) then 36 | gpio.write(2,1) 37 | end 38 | return res 39 | end) 40 | mcunode.connect("4567","eiot.club","wifi","123456abc") -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/LEDremote/indextpl.html: -------------------------------------------------------------------------------- 1 | 互联网控制nodemcuLED 2 | 3 | 4 | 5 | 6 |

互联网控制NodeMcu的IO

7 |
8 | GPIO0:
9 | 10 | 11 |
12 |
13 | 34 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/LEDremote/init.lua: -------------------------------------------------------------------------------- 1 | local mcunode = require "mcunode" 2 | 3 | --url:http://mcunodeserver-ip/proxy//gpio?pin=1&val=0 4 | --return:status=success 5 | mcunode.handle("/gpio",function(req,res) 6 | local pin = req.getParam("pin") 7 | local val = req.getParam("val") 8 | if( pin ~= nil) and (val ~= nil) then 9 | print("pin: "..pin .." , val: " ..val) 10 | gpio.mode(pin, gpio.OUTPUT) 11 | gpio.write(pin, val) 12 | res.setAttribute("status","success") 13 | end 14 | return res 15 | end) 16 | mcunode.handle("/test",function(req,res) 17 | local name = req.getParam("name") 18 | res.setAttribute("name",name) 19 | res.body="wodename:{{name}}" 20 | return res 21 | end) 22 | --url:http://mcunodeserver-ip/proxy//index.html?name=farry&work=student 23 | mcunode.handle("/index.html",function(req,res) 24 | local p 25 | local pin = req.getParam("pin") 26 | for i=0 , 12 do 27 | gpio.mode(i, gpio.OUTPUT) 28 | end 29 | if (pin~=nil) then 30 | res.body="ok" 31 | a,b=string.find(pin,'ON') 32 | if (a~=nil) then 33 | c,d=string.find(pin,'%d%d') 34 | if (c~=nil) then 35 | p=string.sub(pin,c,d) 36 | else 37 | p=string.sub(pin,string.find(pin,'%d')) 38 | end 39 | gpio.write(p,1) 40 | else 41 | c,d=string.find(pin,'%d%d') 42 | if (c~=nil) then 43 | p=string.sub(pin,c,d) 44 | else 45 | p=string.sub(pin,string.find(pin,'%d')) 46 | end 47 | gpio.write(p,0) 48 | end 49 | elseif (pin==nil) then 50 | res.file = "indextpl.html" 51 | end 52 | return res 53 | end) 54 | mcunode.connect("4567","eiot.club","wifi","123456abc") 55 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/OnLineTerminalAndOTG/init.lua: -------------------------------------------------------------------------------- 1 | id = 'yourid' --Device ID 2 | ssid = 'yourSSID' --WiFi Name 3 | ssidpwd = 'WiFiPassword' --view on http://www.mcunode.com/proxy// like:http://www.mcunode.com/proxy/4567/index.html 4 | ip="yourServerIpOrHostName" --Eg:"192.168.1.105" or“www.mcunode.com” 5 | function ls() 6 | local l = file.list() 7 | for k,v in pairs(l) do 8 | print("name:"..k..", size:"..v) 9 | end 10 | end 11 | function cat(filename) 12 | local line 13 | file.open(filename, "r") 14 | while 1 do 15 | line = file.readline() 16 | if line == nil then 17 | break 18 | end 19 | line = string.gsub(line, "\n", "") 20 | print(line) 21 | end 22 | file.close() 23 | end 24 | function startServer() 25 | print(wifi.sta.getip()) 26 | sk=net.createConnection(net.TCP, 0) 27 | sk:on("receive", function(sck, c) node.input(c) end ) --print(c) 28 | sk:on("connection", function(sck, c) 29 | --print(c) 30 | sk:send(id) 31 | tmr.alarm(2, 30000, 1, function() 32 | sk:send('

') 33 | end) 34 | function s_output(str) 35 | if (sk~=nil and str~='') then 36 | sk:send(str) 37 | end 38 | end 39 | node.output(s_output,1) 40 | end ) 41 | sk:on("disconnection",function(conn,c) 42 | --node.output(nil) 43 | print('reconnect') 44 | sk:connect(8001,ip) 45 | sk:send(id) 46 | end) 47 | sk:connect(8001,ip) 48 | end 49 | wifi.setmode(wifi.STATION) 50 | wifi.sta.config(ssid,ssidpwd) --set your ap info !!!!!! 51 | wifi.sta.autoconnect(1) 52 | tmr.alarm(1, 1000, 1, function() 53 | if wifi.sta.getip()==nil then 54 | print("Connect AP, Waiting...") 55 | else 56 | startServer() 57 | tmr.stop(1) 58 | end 59 | end) -------------------------------------------------------------------------------- /mcunode/controllers/proxy.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "time" 6 | "strings" 7 | ) 8 | 9 | type ProxyController struct { 10 | beego.Controller 11 | } 12 | 13 | func (c *ProxyController) Get() { 14 | id := c.Ctx.Input.Param(":id") 15 | //file := c.Ctx.Input.Param(":splat") 16 | //c.Ctx.Input.Params() 17 | URI:=c.Ctx.Request.RequestURI 18 | //fmt.Printf(URI) 19 | url:=strings.Replace(URI, "/proxy/"+id+"/", "", -1) 20 | //fmt.Printf(url) 21 | //c.Data["id"] = id 22 | //c.Data["file"] = file 23 | delete(httpmsg,id) 24 | msg:="" 25 | wspublish <- wsEvent(id, []byte(url)) 26 | //c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8") 27 | if strings.Contains(url, ".css") { 28 | c.Ctx.Output.Header("Content-Type", "text/css; charset=utf-8") 29 | }else if strings.Contains(url, ".js") { 30 | c.Ctx.Output.Header("Content-Type", "application/x-javascript; charset=utf-8") 31 | }else { 32 | c.Ctx.Output.Header("Content-Type", "text/html; charset=utf-8") 33 | } 34 | time.Sleep(time.Millisecond*650) 35 | if v, ok := httpmsg[id]; ok { 36 | msg=v 37 | delete(httpmsg,id) 38 | //fmt.Printf("start") 39 | c.Ctx.WriteString(msg) 40 | return 41 | }else { 42 | time.Sleep(time.Millisecond*200) 43 | if v, ok := httpmsg[id]; ok { 44 | msg = v 45 | delete(httpmsg, id) 46 | //fmt.Printf("start") 47 | c.Ctx.WriteString(msg) 48 | return 49 | }else{ 50 | time.Sleep(time.Millisecond*300) 51 | if v, ok := httpmsg[id]; ok { 52 | msg = v 53 | delete(httpmsg, id) 54 | //fmt.Printf("start") 55 | c.Ctx.WriteString(msg) 56 | return 57 | }else{ 58 | c.Ctx.WriteString("TimeOut") 59 | return 60 | } 61 | } 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /mcunode/build.sh: -------------------------------------------------------------------------------- 1 | #Ubuntu test ok,install upx,set : 2 | PATH="$HOME/go1.9/go/bin:$PATH" #PATH for Go bin file 3 | export GOPATH="$HOME/go" #GOPATH 4 | 5 | 6 | env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w" -o ./mcunode_darwin_amd64 7 | env CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "-s -w" -o ./mcunode_linux_386 8 | env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o ./mcunode_linux_amd64 9 | env CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "-s -w" -o ./mcunode_linux_arm 10 | env CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "-s -w" -o ./mcunode_windows_386.exe 11 | env CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o ./mcunode_windows_amd64.exe 12 | env CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "-s -w" -o ./mcunode_linux_mips64 13 | env CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "-s -w" -o ./mcunode_linux_mips64le 14 | env CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "-s -w" -o ./mcunode_linux_mips 15 | env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "-s -w" -o ./mcunode_linux_mipsle 16 | 17 | upx ./mcunode_darwin_amd64 18 | upx ./mcunode_linux_386 19 | upx ./mcunode_linux_amd64 20 | upx ./mcunode_linux_arm 21 | upx ./mcunode_windows_386.exe 22 | upx ./mcunode_windows_amd64.exe 23 | upx ./mcunode_linux_mips64 24 | upx ./mcunode_linux_mips64le 25 | upx ./mcunode_linux_mips 26 | upx ./mcunode_linux_mipsle 27 | 28 | tar czvf mcunode_darwin_amd64.tar.gz views static mcunode_darwin_amd64 29 | tar czvf mcunode_linux_386.tar.gz views static mcunode_linux_386 30 | tar czvf mcunode_linux_amd64.tar.gz views static mcunode_linux_amd64 31 | tar czvf mcunode_linux_arm.tar.gz views static mcunode_linux_arm 32 | tar czvf mcunode_windows_386.tar.gz views static mcunode_windows_386.exe 33 | tar czvf mcunode_windows_amd64.tar.gz views static mcunode_windows_amd64.exe 34 | tar czvf mcunode_linux_mips64.tar.gz views static mcunode_linux_mips64 35 | tar czvf mcunode_linux_mips64le.tar.gz views static mcunode_linux_mips64le 36 | tar czvf mcunode_linux_mips.tar.gz views static mcunode_linux_mips 37 | tar czvf mcunode_linux_mipsle.tar.gz views static mcunode_linux_mipsle 38 | -------------------------------------------------------------------------------- /mcunode/views/terminal.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | McuNode Terminal-设备id:{{ .id }} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 29 |


30 |

使用McuNode Terminal连接NodeMcu,在线控制和开发:

31 |
项目地址:https://github.com/IoTServ/McuNode
32 |
33 |
34 |
35 | 36 |
37 |

可用快捷命令(xx.lua代表一个lua文件):

38 | ls ,     39 | reboot ,     40 | rm xxx.lua ,     41 | cat xxx.lua ,     42 | dofile xxx.lua   43 |
44 |
45 |
46 |
Filename: 47 |
48 | 49 |
50 |
51 |
52 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Please use https://github.com/OpenIoTHub/OpenIoTHub for remote control 2 | # 当前项目已经封存,请使用 https://github.com/OpenIoTHub/OpenIoTHub 来获得esp8266等的设备的远程访问能力 3 | ## McuNode-server 4 | 5 | ### Free servers who use this program list : 6 | * http://eiot.club/ 7 | 8 | #### McuNode server side,McuNode私有化服务端(ThreeFileVersion Recommend) 9 | 10 | 11 | ###### powered by BeeGo Firmwork 12 | 13 | ### 运行需要同时把对应架构的二进制程序和static与views两个文件夹放在同一个文件夹中 14 | 15 | MCUNODE连接此服务端的8001 16 | 17 | 浏览器打开 http://127.0.0.1:<80/8080>/ 或者对应的公网ip 18 | 19 | #### NODEMCU推荐使用https://github.com/IoTServ/McuNode-Lib 连接,该库集成了两种功能在一起并存 20 | #####  当然你也可以使用分开的程序来定制自己的程序,https://github.com/IoTServ/McuNode 21 | 22 | #### 树莓派请使用LinuxArm和两个文件夹 或者你使用单文件的版本 23 | 24 | ##McuNode简介: 25 | ### 总览: 26 | #### McuNode是一个主要针对于NodeMcu的服务端(包含在NodeMcu上运行的支持库),使用者可以运行自己的服务端为自己nodemcu提供云支持,当然你也可以将此服务端提供给他人使用,当前服务端由go语言编写理论上一般单核服务器可以支持多达几万的nodemcu同时连接提供服务。本项目主要支持如下功能: 27 | * 提供在线IDE功能(IDE提供一个基于web的云串口功能,完全实现原本的串口的lua解释器的访问功能;并且提供远程Lua程序升级功能实现基于互联网的完全的控制能力) 28 | ![image](https://github.com/IoTServ/McuNode-server/blob/master/imgs/mcunode.png?raw=true) 29 | ![image](https://github.com/IoTServ/McuNode-server/blob/master/imgs/download.png?raw=true) 30 | * 提供一个类似于Nginx的web代理功能,它可以通过一个可以通过互联网访问的服务器访问nodemcu提供的网页,以此nodemcu编写的web server不仅可以在局域网可以访问,更重要的是McuNode-Lib还提供了一个很棒的文本框架帮助你完成这项工作,包括参数获取和模板文件的渲染等 31 | ![image](https://github.com/IoTServ/McuNode-server/blob/master/imgs/webProxy.png?raw=true) 32 | ![image](https://github.com/IoTServ/McuNode-server/blob/master/NODEMCU%20Lua%20Demo(template%20file%20included)/WebProxyDemo/LEDremote/%E6%88%AA%E5%9B%BE.png?raw=true) 33 | ### 使用方法: 34 | * 你可以使用我们提供的库(https://github.com/IoTServ/McuNode-Lib 通过简单的几行代码就可以体验大部分功能: 35 | ~~~Lua 36 | local mcunode = require "mcunode" 37 | mcunode.connect("","","","") --自定义ID和使用的服务器地址(域名或ip),然后就是连接的热点信息 38 | ~~~ 39 | 复杂一些的例子: 40 | ~~~Lua 41 | local mcunode = require "mcunode" 42 | 43 | --url:http://mcunodeserver-ip/proxy//gpio?pin=1&val=0 44 | --return:status=success 45 | mcunode.handle("/gpio",function(req,res) 46 | local pin = req.getParam("pin") 47 | local val = req.getParam("val") 48 | if( pin ~= nil) and (val ~= nil) then 49 | print("pin: "..pin .." , val: " ..val) 50 | gpio.mode(pin, gpio.OUTPUT) 51 | gpio.write(pin, val) 52 | res.setAttribute("status","success") 53 | end 54 | return res 55 | end) 56 | mcunode.handle("/test",function(req,res) 57 | local name = req.getParam("name") 58 | res.setAttribute("name",name) 59 | res.body="wodename:{{name}}" 60 | return res 61 | end) 62 | --url:http://mcunodeserver-ip/proxy//index.html?name=farry&work=student 63 | mcunode.handle("/index.html",function(req,res) 64 | local name = req.getParam("name") 65 | res.setAttribute("name",name) 66 | local work = req.getParam("work") 67 | res.setAttribute("work",work) 68 | res.file = "indextpl.html" -- ...

{{name}}

... 69 | return res 70 | end) 71 | mcunode.connect("","","","") 72 | ~~~ 73 | 以上的复杂一些的例子需要一个模板文件indextpl.html,内容如下: 74 | ~~~Html 75 |

HELLO Farry

76 | {{name}}:{{work}} 77 |

HELLO Farry

78 |

HELLO Farry

79 |

HELLO Farry

80 |

HELLO Farry

81 |

HELLO Farry

82 | ~~~ 83 | 这个模板会被注册为/index.html的地址所使用,持续中先从URL中获取两个参数然后将两个参数又渲染到模板反馈给用户 84 | #### 而且以上两个程序已经同时支持了在线IDE的功能 85 | 86 | * 当然如果你觉得有些功能用不上或者库太大,你也可以从这里:https://github.com/IoTServ/McuNode-server/tree/master/NODEMCU%E7%94%A8Lua%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B 找到一些有用的信息定制自己的代码 87 | ### 非常希望 有人能提供运行本服务端的实例给大家使用,如果有请与我联系,我将在这里提供相关信息 88 | -------------------------------------------------------------------------------- /mcunode/static/js/lua.min.js: -------------------------------------------------------------------------------- 1 | !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("lua",function(e,t){function n(e){return new RegExp("^(?:"+e.join("|")+")","i")}function a(e){return new RegExp("^(?:"+e.join("|")+")$","i")}function r(e){for(var t=0;e.eat("=");)++t;return e.eat("["),t}function o(e,t){var n=e.next();return"-"==n&&e.eat("-")?e.eat("[")&&e.eat("[")?(t.cur=i(r(e),"comment"))(e,t):(e.skipToEnd(),"comment"):'"'==n||"'"==n?(t.cur=u(n))(e,t):"["==n&&/[\[=]/.test(e.peek())?(t.cur=i(r(e),"string"))(e,t):/\d/.test(n)?(e.eatWhile(/[\w.%]/),"number"):/[\w_]/.test(n)?(e.eatWhile(/[\w\\\-_.]/),"variable"):null}function i(e,t){return function(n,a){for(var r,i=null;null!=(r=n.next());)if(null==i)"]"==r&&(i=0);else if("="==r)++i;else{if("]"==r&&i==e){a.cur=o;break}i=null}return t}}function u(e){return function(t,n){for(var a,r=!1;null!=(a=t.next())&&(a!=e||r);)r=!r&&"\\"==a;return r||(n.cur=o),"string"}}var l=e.indentUnit,s=a(t.specials||[]),c=a(["_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load","loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require","select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall","coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield","debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable","debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable","debug.setupvalue","debug.traceback","close","flush","lines","read","seek","setvbuf","write","io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin","io.stdout","io.tmpfile","io.type","io.write","math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg","math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max","math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh","math.sqrt","math.tan","math.tanh","os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale","os.time","os.tmpname","package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload","package.seeall","string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub","string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper","table.concat","table.insert","table.maxn","table.remove","table.sort"]),m=a(["and","break","elseif","false","nil","not","or","return","true","function","end","if","then","else","do","while","repeat","until","for","in","local"]),d=a(["function","if","repeat","do","\\(","{"]),g=a(["end","until","\\)","}"]),f=n(["end","until","\\)","}","else","elseif"]);return{startState:function(e){return{basecol:e||0,indentDepth:0,cur:o}},token:function(e,t){if(e.eatSpace())return null;var n=t.cur(e,t),a=e.current();return"variable"==n&&(m.test(a)?n="keyword":c.test(a)?n="builtin":s.test(a)&&(n="variable-2")),"comment"!=n&&"string"!=n&&(d.test(a)?++t.indentDepth:g.test(a)&&--t.indentDepth),n},indent:function(e,t){var n=f.test(t);return e.basecol+l*(e.indentDepth-(n?1:0))},lineComment:"--",blockCommentStart:"--[[",blockCommentEnd:"]]"}}),e.defineMIME("text/x-lua","lua")}); 2 | //# sourceMappingURL=lua.min.js.map -------------------------------------------------------------------------------- /mcunode/controllers/mcuserver.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/gorilla/websocket" 5 | 6 | "github.com/IoTServ/McuNode-server/mcunode/models" 7 | "net" 8 | "runtime" 9 | "fmt" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | func wsEvent(id string, msg []byte) models.Event { 15 | return models.Event{id, msg} 16 | } 17 | 18 | func mcuEvent(id string, msg []byte) models.Event { 19 | return models.Event{id, msg} 20 | } 21 | 22 | func Join(user string, ws *websocket.Conn) { 23 | fmt.Printf("Join") 24 | subscribe <- Subscriber{Id: user, Conn: ws} 25 | } 26 | type Subscriber struct { 27 | Id string 28 | Conn *websocket.Conn // Only for WebSocket users; otherwise nil. 29 | } 30 | 31 | var ( 32 | mcu map[string]net.Conn 33 | ws map[string]*websocket.Conn 34 | httpmsg map[string]string 35 | // Send events here to publish them. 36 | wspublish = make(chan models.Event, 100) 37 | mcupublish = make(chan models.Event, 100) 38 | subscribe = make(chan Subscriber, 100) 39 | ) 40 | 41 | // This function handles all incoming chan messages. 42 | func mcuhandler(id string,conn net.Conn) { 43 | fmt.Printf("mcu-id:"+id) 44 | //conn.SetReadDeadline(time.Now().Add(time.Second*6)) 45 | //conn.SetWriteDeadline(time.Now().Add(time.Second*3)) 46 | if v, ok := mcu[id]; ok { 47 | v.Close() 48 | delete(mcu,id) 49 | } 50 | mcu[id]=conn 51 | for { 52 | var recv []byte = make([]byte, 10240) 53 | if conn.SetReadDeadline(time.Now().Add(time.Minute*60))!=nil{ 54 | conn.Close() 55 | fmt.Printf("设置超时退出!") 56 | runtime.Goexit() 57 | } 58 | n,e:=conn.Read(recv) 59 | if e!=nil{ 60 | conn.Close() 61 | // delete(mcu,id) 62 | fmt.Printf("读取错误退出!"+e.Error()) 63 | runtime.Goexit() 64 | } 65 | if conn.SetReadDeadline(time.Time{}) !=nil{ 66 | conn.Close() 67 | fmt.Printf("取消超时退出!") 68 | runtime.Goexit() 69 | } 70 | msg:=recv[:n] 71 | if string(msg)!="" && string(msg)!="

" { 72 | str := strings.Replace(string(msg), "

", "", -1) 73 | mcupublish <- mcuEvent(id, []byte(str)) 74 | } 75 | } 76 | } 77 | 78 | func wshandler(newws Subscriber) { 79 | // Message receive loop. 80 | id :=newws.Id 81 | wsconn :=newws.Conn 82 | fmt.Printf("ws-id:"+id) 83 | if v, ok := ws[id]; ok { 84 | v.Close() 85 | delete(ws,id) 86 | } 87 | ws[id]=wsconn 88 | for { 89 | if wsconn.SetReadDeadline(time.Now().Add(time.Minute*60))!=nil{ 90 | wsconn.Close() 91 | fmt.Printf("设置超时退出!") 92 | runtime.Goexit() 93 | } 94 | _, p, err := wsconn.ReadMessage() 95 | if err != nil { 96 | wsconn.Close() 97 | fmt.Printf("WS读取超时退出!!") 98 | runtime.Goexit() 99 | } 100 | if wsconn.SetReadDeadline(time.Time{}) !=nil{ 101 | wsconn.Close() 102 | fmt.Printf("WS取消超时退出!") 103 | runtime.Goexit() 104 | } 105 | wspublish <- wsEvent(id, p) 106 | } 107 | } 108 | 109 | func runmcuhandler(l net.Listener) { 110 | for { clientconnn, _ := l.Accept() 111 | var recv []byte = make([]byte, 10240) 112 | n, _ := clientconnn.Read(recv) 113 | id := string(recv[:n]) 114 | go mcuhandler(id, clientconnn) 115 | } 116 | } 117 | 118 | func runwshandler() { 119 | for { 120 | select { 121 | case newws := <-subscribe: 122 | go wshandler(newws) 123 | } 124 | } 125 | } 126 | 127 | func bridge() { 128 | for { 129 | select { 130 | //case <-time.After(time.Second * 2): <-mcupublish 131 | case mcumsg := <-mcupublish: 132 | id:=mcumsg.User 133 | msg:=mcumsg.Content 134 | fmt.Printf("ws开始处理") 135 | if v, ok := ws[id]; ok { 136 | fmt.Println(id+"ws存在,并发送到WS") 137 | error:=v.WriteMessage(1,msg) 138 | if error !=nil { 139 | v.Close() 140 | //delete(ws,id) 141 | //mcupublish<-mcumsg 142 | httpmsg[id] = httpmsg[id]+string(msg) 143 | } 144 | 145 | } else { 146 | //mcupublish<-mcumsg 147 | httpmsg[id] = httpmsg[id]+string(msg) 148 | fmt.Println("WS Key Not Found") 149 | } 150 | 151 | case wsmsg := <-wspublish: 152 | fmt.Printf("wsmsg收到消息") 153 | id:=wsmsg.User 154 | msg:=wsmsg.Content 155 | if v, ok := mcu[id]; ok { 156 | if string(msg)!="" { 157 | fmt.Println(id + "mcu存在"+string(msg)) 158 | _,error:=v.Write(msg) 159 | if error!=nil{ 160 | v.Close() 161 | fmt.Printf(id+"设备离线") 162 | } 163 | } 164 | }else {fmt.Println("MCU Key Not Found")} 165 | } 166 | 167 | } 168 | } 169 | 170 | func init() { 171 | ws = make(map[string]*websocket.Conn) 172 | mcu = make(map[string]net.Conn) 173 | httpmsg = make(map[string]string) 174 | fmt.Printf("MCUNODE (McuNode.com) server started!\n") 175 | runtime.GOMAXPROCS(runtime.NumCPU()) 176 | l, _ := net.Listen("tcp", ":8001") 177 | go runmcuhandler(l) 178 | go runwshandler() 179 | go bridge() 180 | } 181 | -------------------------------------------------------------------------------- /mcunode/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | McuNode物联网云服务 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 40 |


41 |
42 |
43 |
44 |

使用McuNode Terminal连接NodeMcu,在线控制和开发:

45 |
项目地址:https://github.com/IoTServ/McuNode
46 |
服务端地址:https://github.com/IoTServ/McuNode-server
47 |
库地址:https://github.com/IoTServ/McuNode-Lib
48 |
init.lua demo例子
49 | 82 |
indextpl.html 模板文件
83 | 91 |

92 |

请输入id(init.lua中设置的id):

93 | 94 | 95 |
96 |
97 |
98 |
99 | 100 | 107 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /mcunode/static/js/matchbrackets.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && 13 | (document.documentMode == null || document.documentMode < 8); 14 | 15 | var Pos = CodeMirror.Pos; 16 | 17 | var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; 18 | 19 | function findMatchingBracket(cm, where, strict, config) { 20 | var line = cm.getLineHandle(where.line), pos = where.ch - 1; 21 | var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; 22 | if (!match) return null; 23 | var dir = match.charAt(1) == ">" ? 1 : -1; 24 | if (strict && (dir > 0) != (pos == where.ch)) return null; 25 | var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); 26 | 27 | var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); 28 | if (found == null) return null; 29 | return {from: Pos(where.line, pos), to: found && found.pos, 30 | match: found && found.ch == match.charAt(0), forward: dir > 0}; 31 | } 32 | 33 | // bracketRegex is used to specify which type of bracket to scan 34 | // should be a regexp, e.g. /[[\]]/ 35 | // 36 | // Note: If "where" is on an open bracket, then this bracket is ignored. 37 | // 38 | // Returns false when no bracket was found, null when it reached 39 | // maxScanLines and gave up 40 | function scanForBracket(cm, where, dir, style, config) { 41 | var maxScanLen = (config && config.maxScanLineLength) || 10000; 42 | var maxScanLines = (config && config.maxScanLines) || 1000; 43 | 44 | var stack = []; 45 | var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; 46 | var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) 47 | : Math.max(cm.firstLine() - 1, where.line - maxScanLines); 48 | for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { 49 | var line = cm.getLine(lineNo); 50 | if (!line) continue; 51 | var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; 52 | if (line.length > maxScanLen) continue; 53 | if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); 54 | for (; pos != end; pos += dir) { 55 | var ch = line.charAt(pos); 56 | if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { 57 | var match = matching[ch]; 58 | if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); 59 | else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; 60 | else stack.pop(); 61 | } 62 | } 63 | } 64 | return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; 65 | } 66 | 67 | function matchBrackets(cm, autoclear, config) { 68 | // Disable brace matching in long lines, since it'll cause hugely slow updates 69 | var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; 70 | var marks = [], ranges = cm.listSelections(); 71 | for (var i = 0; i < ranges.length; i++) { 72 | var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); 73 | if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { 74 | var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; 75 | marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); 76 | if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) 77 | marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); 78 | } 79 | } 80 | 81 | if (marks.length) { 82 | // Kludge to work around the IE bug from issue #1193, where text 83 | // input stops going to the textare whever this fires. 84 | if (ie_lt8 && cm.state.focused) cm.focus(); 85 | 86 | var clear = function() { 87 | cm.operation(function() { 88 | for (var i = 0; i < marks.length; i++) marks[i].clear(); 89 | }); 90 | }; 91 | if (autoclear) setTimeout(clear, 800); 92 | else return clear; 93 | } 94 | } 95 | 96 | var currentlyHighlighted = null; 97 | function doMatchBrackets(cm) { 98 | cm.operation(function() { 99 | if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} 100 | currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); 101 | }); 102 | } 103 | 104 | CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { 105 | if (old && old != CodeMirror.Init) { 106 | cm.off("cursorActivity", doMatchBrackets); 107 | if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} 108 | } 109 | if (val) { 110 | cm.state.matchBrackets = typeof val == "object" ? val : {}; 111 | cm.on("cursorActivity", doMatchBrackets); 112 | } 113 | }); 114 | 115 | CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); 116 | CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){ 117 | return findMatchingBracket(this, pos, strict, config); 118 | }); 119 | CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ 120 | return scanForBracket(this, pos, dir, style, config); 121 | }); 122 | }); 123 | -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/简版远程LED控制/mcunode.lua: -------------------------------------------------------------------------------- 1 | local moduleName = "mcunode" 2 | local M = {} 3 | _G[moduleName] = M 4 | 5 | local handlers = {} 6 | 7 | local files = {} 8 | 9 | --plugin 10 | function ls() 11 | local l = file.list() 12 | for k,v in pairs(l) do 13 | print("name:"..k..", size:"..v) 14 | end 15 | end 16 | function cat(filename) 17 | local line 18 | file.open(filename, "r") 19 | while 1 do 20 | line = file.readline() 21 | if line == nil then 22 | break 23 | end 24 | line = string.gsub(line, "\n", "") 25 | print(line) 26 | end 27 | file.close() 28 | end 29 | 30 | local function urlDecode(str) 31 | if str == nil then 32 | return nil 33 | end 34 | str = string.gsub(str, '+', ' ') 35 | str = string.gsub(str, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end) 36 | return str 37 | end 38 | 39 | -- 解析request请求参数 40 | local function parseRequest(data) 41 | --print("data"..data) 42 | local req = {} 43 | local param = nil 44 | req.parameter = {} 45 | req.method = 'GET' 46 | req.protocol = 'http' 47 | -- 解析请求路径及请求参数 48 | _,_,req.path,param = string.find(data,"([^%?]+)%??([^%s]*)") --1 16 gpio pin=1&val=0 path ="gpio?pin=1&val=0" 49 | --print("param"..param) 50 | if param ~= nil then --解析请求参数 51 | --print(param.."not nil") 52 | for key,value in string.gmatch(param,"([^%?%&]+)=([^%?%&]+)") do 53 | --print(key..value) 54 | req.parameter[key] = urlDecode(value) --pin 1 , val 0 param ="gpio?pin=1&val=0" 55 | end 56 | param = nil 57 | end 58 | --print("request path : " .. req.path) 59 | data = nil 60 | req.getParam = function(name) --获取请求参数 61 | if(name == nil) then 62 | return req.parameter 63 | end 64 | return req.parameter[name] --"farry" 65 | end 66 | return req 67 | end 68 | 69 | 70 | 71 | -- tabel to string 72 | local function renderString(subs) 73 | local content = "" 74 | for k,v in pairs(subs) do 75 | content = content.. k .."=" .. v .."," 76 | end 77 | if ( #content == 0 ) then 78 | return nil 79 | end 80 | return string.sub(content,1,#content -1) 81 | end 82 | 83 | -- 渲染返回数据 84 | local function render(conn,res) 85 | local body = nil 86 | local attr = res.attribute 87 | html="" 88 | if res.file then 89 | --print("file") 90 | file.open(res.file,"r") 91 | --print("response file : " .. res.file) 92 | while true do 93 | local line = file.readline() 94 | if line == nil then 95 | break 96 | end 97 | if attr then 98 | for k, v in pairs(attr) do 99 | line= string.gsub(line, '{{'..k..'}}', v) 100 | end 101 | end 102 | --html=html..line 103 | conn:send(line) 104 | line="" 105 | end 106 | file.close() 107 | elseif res.body then 108 | --print("body") 109 | body = res.body 110 | if attr then 111 | for k, v in pairs(attr) do 112 | body = string.gsub(body, '{{'..k..'}}', v) 113 | end 114 | end 115 | --print(body) 116 | html=body 117 | conn:send(html) 118 | elseif attr then 119 | --print("attr") 120 | body = renderString(attr) 121 | if body then 122 | html=body 123 | conn:send(html) 124 | end 125 | end 126 | --print("send"..html) 127 | html=nil 128 | res = nil 129 | body = nil 130 | attr = nil 131 | end 132 | 133 | 134 | local function receive(conn,data) 135 | local s = tmr.now() -- start time 136 | local req = parseRequest(data) 137 | local func = handlers["/"..req.path] 138 | local response = {} 139 | response.attribute = {} --当file或body不为nil时,做变量置换,否则body为attribute解析之后的结果 140 | response.body = nil --响应体 141 | response.file = nil -- 静态文件 142 | response.setAttribute = function(k,v) 143 | if(type(k) == "table") then 144 | for key,val in pairs(k) do 145 | response.attribute[key] = val 146 | end 147 | else 148 | response.attribute[k] = v 149 | end 150 | end 151 | response.getAttribute = function(k) 152 | if(k == nil) then 153 | return response.attribute 154 | end 155 | return response.attribute[k] 156 | end 157 | tmr.wdclr() 158 | if func == nil then -- 没有匹配路径 159 | node.input(data) 160 | function s_output(str) 161 | if (conn~=nil and str~='') then 162 | conn:send(str) 163 | end 164 | end 165 | node.output(s_output,1) 166 | elseif func == "file" then 167 | response.file = req.path 168 | else 169 | response = func(req,response) 170 | end 171 | req = nil 172 | if response then 173 | render(conn,response) 174 | end 175 | response = nil 176 | local e = tmr.now() -- end time 177 | --print("heap:" .. node.heap() .. "bytes, start_time : ".. s .. "us,end_time:".. e .."us,total_time : " .. (e-s) .."us") 178 | collectgarbage("collect") 179 | --node.output(nil) 180 | end 181 | 182 | function M.handle(path, func) 183 | handlers[path] = func 184 | end 185 | 186 | function M.connect( id , host , ssid , pwd ) 187 | conn = net.createConnection(net.TCP, 0) 188 | conn:on("connection", function(sk, c) 189 | sk:send(id) 190 | tmr.alarm(2, 10000, 1, function() sk:send('

') end) 191 | end) 192 | conn:on('receive', receive) 193 | if (ssid~=nil) then 194 | wifi.setmode(wifi.STATION) 195 | wifi.sta.config(ssid,tostring(pwd or "")) --set your ap info !!!!!! 196 | wifi.sta.autoconnect(1) 197 | tmr.alarm(1, 1000, 1, function() 198 | if wifi.sta.getip()==nil then 199 | print("Connect AP, Waiting...") 200 | else 201 | tmr.stop(1) 202 | conn:connect(8001,host) 203 | print("Mcunode Terminal and web proxy is running !\nId is " .. id.." host is "..host) 204 | local l = file.list() 205 | for k,v in pairs (l) do 206 | if not string.find(k,".lc") then 207 | handlers["/"..k] = "file" 208 | end 209 | end 210 | l = nil 211 | for k,v in pairs (handlers) do 212 | print("path:" .. k) 213 | end 214 | --collectgarbage("collect") 215 | --tmr.delay(100000) 216 | print("localhost ip : "..wifi.sta.getip()) 217 | end 218 | end) 219 | end 220 | end 221 | 222 | return M -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/nodemcu_code_lib and demo/mcunode.lua: -------------------------------------------------------------------------------- 1 | local moduleName = "mcunode" 2 | local M = {} 3 | _G[moduleName] = M 4 | 5 | local handlers = {} 6 | 7 | local files = {} 8 | 9 | --plugin 10 | function ls() 11 | local l = file.list() 12 | for k,v in pairs(l) do 13 | print("name:"..k..", size:"..v) 14 | end 15 | end 16 | function cat(filename) 17 | local line 18 | file.open(filename, "r") 19 | while 1 do 20 | line = file.readline() 21 | if line == nil then 22 | break 23 | end 24 | line = string.gsub(line, "\n", "") 25 | print(line) 26 | end 27 | file.close() 28 | end 29 | 30 | local function urlDecode(str) 31 | if str == nil then 32 | return nil 33 | end 34 | str = string.gsub(str, '+', ' ') 35 | str = string.gsub(str, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end) 36 | return str 37 | end 38 | 39 | -- 解析request请求参数 40 | local function parseRequest(data) 41 | --print("data"..data) 42 | local req = {} 43 | local param = nil 44 | req.parameter = {} 45 | req.method = 'GET' 46 | req.protocol = 'http' 47 | -- 解析请求路径及请求参数 48 | _,_,req.path,param = string.find(data,"([^%?]+)%??([^%s]*)") --1 16 gpio pin=1&val=0 path ="gpio?pin=1&val=0" 49 | --print("param"..param) 50 | if param ~= nil then --解析请求参数 51 | --print(param.."not nil") 52 | for key,value in string.gmatch(param,"([^%?%&]+)=([^%?%&]+)") do 53 | --print(key..value) 54 | req.parameter[key] = urlDecode(value) --pin 1 , val 0 param ="gpio?pin=1&val=0" 55 | end 56 | param = nil 57 | end 58 | --print("request path : " .. req.path) 59 | data = nil 60 | req.getParam = function(name) --获取请求参数 61 | if(name == nil) then 62 | return req.parameter 63 | end 64 | return req.parameter[name] --"farry" 65 | end 66 | return req 67 | end 68 | 69 | 70 | 71 | -- tabel to string 72 | local function renderString(subs) 73 | local content = "" 74 | for k,v in pairs(subs) do 75 | content = content.. k .."=" .. v .."," 76 | end 77 | if ( #content == 0 ) then 78 | return nil 79 | end 80 | return string.sub(content,1,#content -1) 81 | end 82 | 83 | -- 渲染返回数据 84 | local function render(conn,res) 85 | local body = nil 86 | local attr = res.attribute 87 | html="" 88 | if res.file then 89 | --print("file") 90 | file.open(res.file,"r") 91 | --print("response file : " .. res.file) 92 | while true do 93 | local line = file.readline() 94 | if line == nil then 95 | break 96 | end 97 | if attr then 98 | for k, v in pairs(attr) do 99 | line= string.gsub(line, '{{'..k..'}}', v) 100 | end 101 | end 102 | --html=html..line 103 | conn:send(line) 104 | line="" 105 | end 106 | file.close() 107 | elseif res.body then 108 | --print("body") 109 | body = res.body 110 | if attr then 111 | for k, v in pairs(attr) do 112 | body = string.gsub(body, '{{'..k..'}}', v) 113 | end 114 | end 115 | --print(body) 116 | html=body 117 | conn:send(html) 118 | elseif attr then 119 | --print("attr") 120 | body = renderString(attr) 121 | if body then 122 | html=body 123 | conn:send(html) 124 | end 125 | end 126 | --print("send"..html) 127 | html=nil 128 | res = nil 129 | body = nil 130 | attr = nil 131 | end 132 | 133 | 134 | local function receive(conn,data) 135 | local s = tmr.now() -- start time 136 | local req = parseRequest(data) 137 | local func = handlers["/"..req.path] 138 | local response = {} 139 | response.attribute = {} --当file或body不为nil时,做变量置换,否则body为attribute解析之后的结果 140 | response.body = nil --响应体 141 | response.file = nil -- 静态文件 142 | response.setAttribute = function(k,v) 143 | if(type(k) == "table") then 144 | for key,val in pairs(k) do 145 | response.attribute[key] = val 146 | end 147 | else 148 | response.attribute[k] = v 149 | end 150 | end 151 | response.getAttribute = function(k) 152 | if(k == nil) then 153 | return response.attribute 154 | end 155 | return response.attribute[k] 156 | end 157 | tmr.wdclr() 158 | if func == nil then -- 没有匹配路径 159 | node.input(data) 160 | function s_output(str) 161 | if (conn~=nil and str~='') then 162 | conn:send(str) 163 | end 164 | end 165 | node.output(s_output,1) 166 | elseif func == "file" then 167 | response.file = req.path 168 | else 169 | response = func(req,response) 170 | end 171 | req = nil 172 | if response then 173 | render(conn,response) 174 | end 175 | response = nil 176 | local e = tmr.now() -- end time 177 | --print("heap:" .. node.heap() .. "bytes, start_time : ".. s .. "us,end_time:".. e .."us,total_time : " .. (e-s) .."us") 178 | collectgarbage("collect") 179 | --node.output(nil) 180 | end 181 | 182 | function M.handle(path, func) 183 | handlers[path] = func 184 | end 185 | 186 | function M.connect( id , host , ssid , pwd ) 187 | conn = net.createConnection(net.TCP, 0) 188 | conn:on("connection", function(sk, c) 189 | sk:send(id) 190 | tmr.alarm(2, 10000, 1, function() sk:send('

') end) 191 | end) 192 | conn:on('receive', receive) 193 | if (ssid~=nil) then 194 | wifi.setmode(wifi.STATION) 195 | wifi.sta.config(ssid,tostring(pwd or "")) --set your ap info !!!!!! 196 | wifi.sta.autoconnect(1) 197 | tmr.alarm(1, 1000, 1, function() 198 | if wifi.sta.getip()==nil then 199 | print("Connect AP, Waiting...") 200 | else 201 | tmr.stop(1) 202 | conn:connect(8001,host) 203 | print("Mcunode Terminal and web proxy is running !\nId is " .. id.." host is "..host) 204 | local l = file.list() 205 | for k,v in pairs (l) do 206 | if not string.find(k,".lc") then 207 | handlers["/"..k] = "file" 208 | end 209 | end 210 | l = nil 211 | for k,v in pairs (handlers) do 212 | print("path:" .. k) 213 | end 214 | --collectgarbage("collect") 215 | --tmr.delay(100000) 216 | print("localhost ip : "..wifi.sta.getip()) 217 | end 218 | end) 219 | end 220 | end 221 | 222 | return M -------------------------------------------------------------------------------- /NODEMCU Lua Demo(template file included)/WebProxyDemo/LEDremote/mcunode.lua: -------------------------------------------------------------------------------- 1 | local moduleName = "mcunode" 2 | local M = {} 3 | _G[moduleName] = M 4 | 5 | local handlers = {} 6 | 7 | local files = {} 8 | 9 | --plugin 10 | function ls() 11 | local l = file.list() 12 | for k,v in pairs(l) do 13 | print("name:"..k..", size:"..v) 14 | end 15 | end 16 | function cat(filename) 17 | local line 18 | file.open(filename, "r") 19 | while 1 do 20 | line = file.readline() 21 | if line == nil then 22 | break 23 | end 24 | line = string.gsub(line, "\n", "") 25 | print(line) 26 | end 27 | file.close() 28 | end 29 | 30 | local function urlDecode(str) 31 | if str == nil then 32 | return nil 33 | end 34 | str = string.gsub(str, '+', ' ') 35 | str = string.gsub(str, '%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end) 36 | return str 37 | end 38 | 39 | -- 解析request请求参数 40 | local function parseRequest(data) 41 | --print("data"..data) 42 | local req = {} 43 | local param = nil 44 | req.parameter = {} 45 | req.method = 'GET' 46 | req.protocol = 'http' 47 | -- 解析请求路径及请求参数 48 | _,_,req.path,param = string.find(data,"([^%?]+)%??([^%s]*)") --1 16 gpio pin=1&val=0 path ="gpio?pin=1&val=0" 49 | --print("param"..param) 50 | if param ~= nil then --解析请求参数 51 | --print(param.."not nil") 52 | for key,value in string.gmatch(param,"([^%?%&]+)=([^%?%&]+)") do 53 | --print(key..value) 54 | req.parameter[key] = urlDecode(value) --pin 1 , val 0 param ="gpio?pin=1&val=0" 55 | end 56 | param = nil 57 | end 58 | --print("request path : " .. req.path) 59 | data = nil 60 | req.getParam = function(name) --获取请求参数 61 | if(name == nil) then 62 | return req.parameter 63 | end 64 | return req.parameter[name] --"farry" 65 | end 66 | return req 67 | end 68 | 69 | 70 | 71 | -- tabel to string 72 | local function renderString(subs) 73 | local content = "" 74 | for k,v in pairs(subs) do 75 | content = content.. k .."=" .. v .."," 76 | end 77 | if ( #content == 0 ) then 78 | return nil 79 | end 80 | return string.sub(content,1,#content -1) 81 | end 82 | 83 | -- 渲染返回数据 84 | local function render(conn,res) 85 | local body = nil 86 | local attr = res.attribute 87 | html="" 88 | if res.file then 89 | --print("file") 90 | file.open(res.file,"r") 91 | --print("response file : " .. res.file) 92 | while true do 93 | local line = file.readline() 94 | if line == nil then 95 | break 96 | end 97 | if attr then 98 | for k, v in pairs(attr) do 99 | line= string.gsub(line, '{{'..k..'}}', v) 100 | end 101 | end 102 | --html=html..line 103 | conn:send(line) 104 | line="" 105 | end 106 | file.close() 107 | elseif res.body then 108 | --print("body") 109 | body = res.body 110 | if attr then 111 | for k, v in pairs(attr) do 112 | body = string.gsub(body, '{{'..k..'}}', v) 113 | end 114 | end 115 | --print(body) 116 | html=body 117 | conn:send(html) 118 | elseif attr then 119 | --print("attr") 120 | body = renderString(attr) 121 | if body then 122 | html=body 123 | conn:send(html) 124 | end 125 | end 126 | --print("send"..html) 127 | html=nil 128 | res = nil 129 | body = nil 130 | attr = nil 131 | end 132 | 133 | 134 | local function receive(conn,data) 135 | local s = tmr.now() -- start time 136 | local req = parseRequest(data) 137 | local func = handlers["/"..req.path] 138 | local response = {} 139 | response.attribute = {} --当file或body不为nil时,做变量置换,否则body为attribute解析之后的结果 140 | response.body = nil --响应体 141 | response.file = nil -- 静态文件 142 | response.setAttribute = function(k,v) 143 | if(type(k) == "table") then 144 | for key,val in pairs(k) do 145 | response.attribute[key] = val 146 | end 147 | else 148 | response.attribute[k] = v 149 | end 150 | end 151 | response.getAttribute = function(k) 152 | if(k == nil) then 153 | return response.attribute 154 | end 155 | return response.attribute[k] 156 | end 157 | tmr.wdclr() 158 | if func == nil then -- 没有匹配路径 159 | node.input(data) 160 | function s_output(str) 161 | if (conn~=nil and str~='') then 162 | conn:send(str) 163 | end 164 | end 165 | node.output(s_output,1) 166 | elseif func == "file" then 167 | response.file = req.path 168 | else 169 | response = func(req,response) 170 | end 171 | req = nil 172 | if response then 173 | render(conn,response) 174 | end 175 | response = nil 176 | local e = tmr.now() -- end time 177 | --print("heap:" .. node.heap() .. "bytes, start_time : ".. s .. "us,end_time:".. e .."us,total_time : " .. (e-s) .."us") 178 | collectgarbage("collect") 179 | --node.output(nil) 180 | end 181 | 182 | function M.handle(path, func) 183 | handlers[path] = func 184 | end 185 | 186 | function M.connect( id , host , ssid , pwd ) 187 | station_cfg={} 188 | station_cfg.ssid=ssid 189 | station_cfg.pwd=pwd 190 | station_cfg.save=false 191 | station_cfg.auto=true 192 | conn = net.createConnection(net.TCP, 0) 193 | conn:on("connection", function(sk, c) 194 | sk:send(id) 195 | tmr.alarm(2, 100000, 1, function() sk:send('

') end) 196 | end) 197 | conn:on('receive', receive) 198 | if (ssid~=nil) then 199 | wifi.setmode(wifi.STATION) 200 | wifi.sta.config(station_cfg) --set your ap info !!!!!! 201 | wifi.sta.autoconnect(1) 202 | tmr.alarm(1, 1000, 1, function() 203 | if wifi.sta.getip()==nil then 204 | print("Connect AP, Waiting...") 205 | else 206 | tmr.stop(1) 207 | conn:connect(8001,host) 208 | print("Mcunode Terminal and web proxy is running !\nId is " .. id.." host is "..host) 209 | local l = file.list() 210 | for k,v in pairs (l) do 211 | if not string.find(k,".lc") then 212 | handlers["/"..k] = "file" 213 | end 214 | end 215 | l = nil 216 | for k,v in pairs (handlers) do 217 | print("path:" .. k) 218 | end 219 | --collectgarbage("collect") 220 | --tmr.delay(100000) 221 | print("localhost ip : "..wifi.sta.getip()) 222 | end 223 | end) 224 | end 225 | end 226 | 227 | return M 228 | -------------------------------------------------------------------------------- /mcunode/static/js/mcunode.js: -------------------------------------------------------------------------------- 1 | var websocket; 2 | window.addEventListener('load', function() { 3 | var wsUri ="ws://"+window.location.host+"/ws/"+id; 4 | var term = new Terminal({cols: 100,rows: 35}); 5 | term.open(document.getElementById('terminal')); 6 | function runWebSocket() { 7 | websocket = new WebSocket(wsUri); 8 | websocket.onopen = function(evt) { 9 | onOpen(evt) 10 | }; 11 | websocket.onclose = function(evt) { 12 | onClose(evt) 13 | }; 14 | websocket.onmessage = function(evt) { 15 | onMessage(evt) 16 | }; 17 | websocket.onerror = function(evt) { 18 | onError(evt) 19 | }; 20 | } 21 | 22 | function onOpen(evt) { 23 | writeToScreen("CONNECTED"); 24 | doSend("=wifi.sta.getip()"); 25 | } 26 | 27 | function onClose(evt) { 28 | writeToScreen("DISCONNECTED"); 29 | } 30 | 31 | function onMessage(evt) { 32 | s=String(evt.data); 33 | console.log('row data:'+s); 34 | //s=s.substring(0,s.length-3); 35 | s=s.replace(/\n/g,'\r\n'); 36 | writeToScreen('>: '+ s); 37 | //websocket.close(); 38 | } 39 | 40 | function onError(evt) { 41 | writeToScreen('ERROR: '+ evt.data); 42 | } 43 | 44 | function doSend(message) { 45 | writeToScreen("SENT: " + message); 46 | websocket.send(message); 47 | } 48 | 49 | function writeToScreen(message) { 50 | term.write(message+'\r\n>'); 51 | } 52 | runWebSocket(); 53 | // 54 | 55 | var send_data=''; 56 | term.on('data', function(data) { 57 | if (data!='\r'&&data!='\n') { 58 | send_data = send_data + data; 59 | term.write(data); 60 | console.log(data); 61 | } 62 | if (data=='\r'||data=='\n'){ 63 | term.write('\r\n>'); 64 | console.log(send_data); 65 | 66 | var strs=send_data.split(" "); //字符分割 67 | switch(strs[0]){ 68 | case 'ls': 69 | send_data = 'ls()'; 70 | break; 71 | case 'reboot': 72 | send_data = 'node.restart()'; 73 | break; 74 | case 'rm': 75 | var fname=strs[1]; 76 | send_data = 'file.remove(\''+fname+'\')'; 77 | break; 78 | case 'cat': 79 | var fname=strs[1]; 80 | send_data = 'cat(\''+fname+'\')'; 81 | break; 82 | case 'dl': 83 | var host; 84 | var uri; 85 | var fname; 86 | var url=strs[1]; 87 | urlstrs=send_data.split("/"); 88 | host=urlstrs[2]; 89 | uri=urlstrs[3]+'/'+urlstrs[4]; 90 | fname=urlstrs[4]; 91 | if (typeof(strs[2])!='undefined'){ 92 | fname=strs[2]; 93 | } 94 | //from host+uri download a file,save as fname 95 | send_data = 'downloadfile(\''+host+'\',\''+uri+'\',\''+fname+'\')'; 96 | break; 97 | case 'run': 98 | var host; 99 | var uri; 100 | var fname; 101 | var url=strs[1]; 102 | urlstrs= new Array(); 103 | urlstrs=send_data.split("/"); 104 | host=urlstrs[2]; 105 | uri=urlstrs[3]+'/'+urlstrs[4]; 106 | fname=urlstrs[4]; 107 | //from host+uri download a file,save as fname 108 | message = 'downloadfile(\''+host+'\',\''+uri+'\',\''+'run.lua\')'; 109 | websocket.send(message); 110 | send_data = 'dofile(\'run.lua\')'; 111 | break; 112 | case 'dofile': 113 | var fname=strs[1]; 114 | send_data = 'dofile(\''+fname+'\')'; 115 | break; 116 | default: 117 | console.log('没有可以匹配的命令'+send_data); 118 | } 119 | websocket.send(send_data); 120 | send_data=''; 121 | } 122 | }); 123 | 124 | 125 | term.write('Welcome to use \033[1;3;31m McuNode!\033[0m \r\n>'); 126 | }, false); 127 | 128 | 129 | 130 | function writeToMcu(){ 131 | //var code=document.getElementById("code").value.split('\n'); 132 | var innerI = 0; 133 | var code = editor.getValue().split('\n'); 134 | lineleng=code.length; 135 | console.log(lineleng); 136 | filename=document.getElementById("filename").value||'fogot.lua'; 137 | websocket.send('file.remove(\''+filename+'\')'); 138 | sleep(300); 139 | websocket.send('file.open(\''+filename+'\', \'w+\')'); 140 | mytime = setInterval(function () { write() }, 200); 141 | function write() { 142 | if(innerI