Compare commits

...

4 Commits

Author SHA1 Message Date
IoTcat b1d4811c6b finish_lua_core 3 years ago
IoTcat b7c240701e v0.3.4 3 years ago
IoTcat 9b8af1e658 v0.3.3 3 years ago
IoTcat 502f09649f v0.3.1 3 years ago
  1. 11
      init.lua
  2. 4
      package.json
  3. 17
      src/cli/device.js
  4. 2
      src/cli/init.js
  5. 17
      src/cli/modules/reset.js
  6. 14
      src/cli/modules/upload.js
  7. 2
      src/cli/modules/winFlash.js
  8. BIN
      src/drivers/nodemcu/bin/full.bin
  9. 19008
      src/drivers/nodemcu/bin/nodemcu_float_master_20210207-0810.map
  10. BIN
      src/drivers/nodemcu/bin/old3.bin
  11. 935
      src/drivers/nodemcu/lua/init.lua
  12. 271
      src/drivers/nodemcu/lua/init.old.lua
  13. 15
      ttt.js

@ -0,0 +1,11 @@
--set AP mode
wifi.setmode(wifi.SOFTAP)
--config AP
cfg={}
cfg.ssid="myssid"
cfg.pwd="mypassword"
wifi.ap.config(cfg)

@ -1,6 +1,6 @@
{
"name": "wIoT",
"version": "0.3.0",
"name": "wiot",
"version": "0.3.4",
"description": "A software-defined IoT OS basing on NodeJS.",
"main": "index.js",
"repository": "git@github.com:iotcat/wIoT",

@ -5,12 +5,20 @@ module.exports = (yargs) => {
resolve()
}),
upload: async (argv) => new Promise(async resolve => {
ban = new ora(`Preparing NodeMCU...0%`).start();
await reset(argv._[1]);
ban.info('Preparing NodeMCU...10%');
await upload(argv._[1], __dirname+'/../drivers/nodemcu/lua/init.lua');
ban.info('Preparing NodeMCU...30%');
await upload(argv._[1], __dirname+'/../drivers/nodemcu/lua/config.json');
ban.info('Preparing NodeMCU...50%');
await upload(argv._[1], __dirname+'/../drivers/nodemcu/lua/FUNC.json');
ban.info('Preparing NodeMCU...70%');
await upload(argv._[1], __dirname+'/../drivers/nodemcu/lua/__stopped');
ban.info('Preparing NodeMCU...90%');
await reset(argv._[1]);
ban.info('Preparing NodeMCU...100%');
ban.succeed('NodeMCU on '+argv._[1]+' is ready!! You can pull it out now~');
resolve()
}),
terminal: async (argv) => new Promise(async resolve => {
@ -37,7 +45,14 @@ module.exports = (yargs) => {
.command('terminal', "wiot terminal <PortsName>".green + " Open a NodeMCU terminal..", yargs => yargs, async argv => {
await o.terminal(argv);
})
.command('ini', "wiot ini <PortsName>".green + " Init a NodeMCU board..", yargs => yargs, async argv => {
.command('init', "wiot init <PortsName>".green + " Init a NodeMCU board..", yargs => yargs, async argv => {
ban = new ora(`Checking port ${argv._[1]}...`).start();
let deviceList = await winDevList();
if(deviceList.indexOf(argv._[1]) == -1){
ban.fail('No devices on '+argv._[1]+'!!');
return;
}
ban.succeed('Found '+argv._[1]+'!!');
await o.flash(argv);
await o.upload(argv);
})

@ -69,7 +69,7 @@ module.exports = (yargs) => {
yargs = yargs
.command('init', "wiot init <ProjectName> [path]".green + " Create and initiate a new wIoT Project folder", yargs => yargs, async argv => {
.command('ini', "wiot ini <ProjectName> [path]".green + " Create and initiate a new wIoT Project folder", yargs => yargs, async argv => {
await o.init(argv);
})

@ -4,21 +4,14 @@ module.exports = async (port) => {
const path = require('path');
const ora = require('ora');
const root = __dirname + '/../../../';
const nt = require('nodemcu-tool');
const reset = () => {
return new Promise((resolve, reject) => {
ban = new ora(`Reset ${port}...`).start();
let process = execFile(root + 'node_modules/.bin/nodemcu-tool.cmd', ['reset', '-p', port], (err, stdout, stderr) => {
if(err) {
ban.fail(`${port} reset fail!!`);
console.log(stderr);
reject();
}else{
ban.succeed(port+' reset successfully!!');
resolve(stdout);
}
});
return new Promise(async (resolve, reject) => {
await nt.hardreset(port);
await nt.disconnect();
resolve();
});
}

@ -4,18 +4,18 @@ module.exports = async (port, file) => {
const path = require('path');
const ora = require('ora');
const root = __dirname + '/../../../';
const upload = () => {
return new Promise((resolve, reject) => {
ban = new ora(`Upload ${file}...`).start();
let process = execFile(root + 'node_modules/.bin/nodemcu-tool.cmd', ['upload', '-p', port, file], (err, stdout, stderr) => {
//ban = new ora(`Upload ${file}...`).start();
let process = execFile(root + 'node_modules/.bin/nodemcu-tool.cmd', ['upload', '-p', port, file], async (err, stdout, stderr) => {
if(err) {
ban.fail(`${file} uploaded!!`);
console.log(stderr);
reject();
//ban.fail(`${file} uploaded!!`);
//console.log(stderr);
setTimeout(async ()=>{resolve(await upload())}, 1000);
}else{
ban.succeed(file+' uploaded!!');
//ban.succeed(file+' uploaded!!');
resolve(stdout);
}
});

@ -19,7 +19,7 @@ module.exports = async (port, bin) => {
process.stdout.on('data', (data) => {
if(data.toString().substring(0, 3) == '. ['){
ban.info('Flashing...' + data.toString().substring(1));
ban.info('Flashing...' + data.toString().substring(1, 9));
}
if(data.toString().indexOf('[ 100% ]') != -1){
ban.succeed('Flash finished!!');

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

@ -1,271 +1,704 @@
--Global Var
CONFIG = {}
udp = nil --UDP Server
key = nil --Encrypt Key
G = {} --Var Zone
(function(__run)
--wIoT Toolbox
w = {
f = {},
waitList = {},
send = function(ip, port, fid, body, cb)
local sid = func.randomLetter(8)
local o = {
fid = fid,
sid = sid,
id = CONFIG.w.id,
body = body
--Packages Used: file, sjson, http, httpserver, mqtt, encoder, timer, node, wifi, gpio
--package loaded
----------------
local httpserver = dofile('httpserver.lua');
--Global Method Extension
-------------------------
string.split = function( str,reps )
local resultStrList = {}
string.gsub(str,'[^'..reps..']+',function ( w )
table.insert(resultStrList,w)
end)
return resultStrList
end
--Method Declaration
--------------------
local _ = {
_ = {
restart = nil,
reset = nil
},
init = {
http = nil,
mqtt = nil,
onlineFunc = nil
},
config = {
v = nil,
path = '__system/_config.json',
default = {
nid = 'default',
offlineOnly = true,
signalPin = 0,
flag = {
MaxRetryTimes = 2,
MaxResetTimes = 3
},
func = {
offline = {
MaxWaitTime = 60
},
online = {
MaxWaitTime = 60
}
},
fs = {
prefix = {
root = '',
system = '__system/',
data = '__data/'
},
filename = {
nsmap = 'ns.map',
flag = 'flag',
func = 'func.json',
error = 'error.json'
}
},
wifi = {
CheckInterval = 1000,
config = {
ssid = '',
pwd = '',
save = false
}
},
http = {
port = 6789,
api = {
discover = '/discover'
}
},
mqtt = {
host = 'mqtt.yimian.xyz',
port = 1883,
user = nil,
password = nil,
tls = false,
keepaliveTimer = 30,
topicPrefix = '/wiot/default/',
ConnectRetryInterval = 2000,
OfflineRetryInterval = 3000,
PostCheckInterval = 100,
PostTimeout = 10
}
}
},
flag = {
v = nil,
set = nil,
load = nil
},
func = {
id = nil,
offline = nil,
online = nil
},
table = {
merge = nil
},
timer = {
setTimeout = nil,
setInterval = nil
},
signal = {
init = nil,
set = nil,
destroy = nil,
v = nil
},
http = {
v = nil
},
mqtt = {
getTopic = nil,
v = nil
},
f = {
read = nil,
write = nil
},
ns = {
set = nil,
get = nil,
render = nil,
exist = nil,
check = nil,
verify = nil
},
package = {
pack = nil,
depack = nil,
set = nil,
get = nil
},
db = {
public = {
keys = nil,
get = nil,
set = nil,
del = nil,
clear = nil
},
toIndex = nil,
fromIndex = nil,
getFileName = nil
},
msg = {
reg = {
send = {},
post = {}
},
postWaitList = {},
public = {
post = nil,
send = nil,
onPost = nil,
onSend = nil
},
mpost = nil,
msend = nil,
dpost = nil,
dsend = nil
},
api = {
http = {
discover = nil,
msg = nil
},
mqtt = {
msg = nil,
heartbeat = nil,
ns = nil,
func = nil,
restart = nil
}
}
local status, msg = pcall(sjson.encode, o)
udp:send(port, ip, msg)
if cb == nil then return ;end
w.waitList[sid] = false
local resTimer = tmr.create()
local retryTimer = tmr.create()
local retryTimes = CONFIG.w.maxRetryTimes
resTimer:register(CONFIG.w.scanInterval, tmr.ALARM_AUTO, function()
if func.tableKeyExist(w.waitList, sid) and w.waitList[sid] ~= false then
cb(w.waitList[sid])
w.waitList[sid] = nil
resTimer:unregister()
retryTimer:unregister()
collectgarbage("collect")
end
end)
retryTimer:register(CONFIG.w.retryInterval, tmr.ALARM_AUTO, function()
if retryTimes > 0 and func.tableKeyExist(w.waitList, sid) and w.waitList[sid] == false then
udp:send(port, ip, msg)
retryTimes = retryTimes - 1
else
retryTimer:unregister()
collectgarbage("collect")
end
end)
resTimer:start()
retryTimer:start()
end,
receive = function(s, data, port, ip)
print(data)
local status, msg = pcall(sjson.decode, data)
if not status then return end
if not func.tableKeyExist(msg, 'sid') or not func.tableKeyExist(msg, 'body') then return end
--respond mode
print(msg.fid)
if not func.tableKeyExist(msg, 'fid') then
if func.tableKeyExist(w.waitList, msg.sid) then
w.waitList[msg.sid] = msg.body
end
return
};
--Method Defination
-------------------
--_
_._.restart = function(err)
if err then
file.putcontents(_.config.v.fs.prefix.system.._.config.v.fs.filename.error, tostring(err));
end
print(msg.fid)
--request mode
if not func.tableKeyExist(w.f, msg.fid) then return end
local res = w.f[msg.fid](msg.body, {port = port, ip = ip, socket = s, sid = msg.sid, fid = msg.fid});
print(msg.fid)
local resObj = {
sid = msg.sid,
id = CONFIG.w.id,
body = res
}
status, res = pcall(sjson.encode, resObj)
print(res)
s:send(port, ip, res)
end,
heartbeat = function()
local o = {
version = CONFIG.firmware.version,
id = CONFIG.w.id,
ip = wifi.sta.getip(),
port = CONFIG.udp.server.port,
}
--request
print(sjson.encode(o))
udp:send(CONFIG.w.director.port, CONFIG.w.director.ip, sjson.encode(o))
end,
_push = function(hash, s)
w.f[hash] = function(r)
if hash == 'construct' or hash == 'destruct' then
print(s)
loadstring('print("hhhhhhh")')()
loadstring(s)()
return
node.restart();
end
_._.reset = function()
file.remove(_.config.v.fs.prefix.system.._.config.v.fs.filename.error);
file.remove(_.config.v.fs.prefix.system.._.config.v.fs.filename.func);
file.remove(_.config.v.fs.prefix.system.._.config.v.fs.filename.flag);
node.restart();
end
--flag
_.flag.load = function()
_.flag.v = tonumber(file.getcontents(_.config.v.fs.prefix.system.._.config.v.fs.filename.flag));
end
_.flag.set = function(val)
_.config.flag.v = val;
file.putcontents(_.config.v.fs.prefix.system.._.config.v.fs.filename.flag, tostring(val));
end
_.flag.ward = function(f)
f();
_.flag.set(-1);
end
--table
_.table.merge = function(a, b)
if type(a) == 'table' and type(b) == 'table' then
for k,v in pairs(b) do
if type(v) == 'table' and type(a[k] or false) == 'table' then
_.table.merge(a[k],v);
else
a[k]=v;
end
end
end
return a;
end
--timer
_.timer.setTimeout = function(f, time_ms)
return tmr.create():alarm(time_ms, tmr.ALARM_SINGLE, f);
end
_.timer.setInterval = function(f, time_ms)
return tmr.create():alarm(time_ms, tmr.ALARM_AUTO, function(timer)
f(function(delay_time_ms)
if delay_time_ms < 0 then
timer:unregister();
else
timer:stop();
_.timer.setTimeout(function()
timer:start();
end, delay_time_ms);
end
end)
end);
end
--signal
_.signal.init = function()
gpio.mode(_.config.v.signalPin, gpio.OUTPUT);
_.signal.v = tmr.create();
end
_.signal.set = function(interval_ms)
_.signal.v:alarm(interval_ms, tmr.ALARM_AUTO, function()
if gpio.read(_.config.v.signalPin) == gpio.HIGH then
gpio.write(_.config.v.signalPin, gpio.LOW);
else
gpio.write(_.config.v.signalPin, gpio.HIGH);
end
local status, msg = pcall(loadstring('return '..s)(), r)
local data = {
status = status,
data = msg
}
return data
end);
end
_.signal.destroy = function()
gpio.write(_.config.v.signalPin, gpio.HIGH);
_.signal.v:unregister();
_.signal.v = nil;
end
--mqtt
_.mqtt.getTopic = function(s)
return _.config.v.mqtt.topicPrefix.._.config.v.nid..'/'..s;
end
_.mqtt.start = function()
_.mqtt.v:connect(
_.config.v.mqtt.host,
_.config.v.mqtt.port,
_.config.v.mqtt.tls.
function(client)
client:subscribe(_.mqtt.getTopic('msg/#'));
client:subscribe(_.mqtt.getTopic('ctl/#'));
client:publish(_.mqtt.getTopic('status'), 'online', 0, 0);
end,
function(client, reason)
_.timer.setTimeout(_.mqtt.start, _.config.v.mqtt.ConnectRetryInterval);
end
);
end
--f
_.f.read = function(f--[[filename]])
local status, obj = pcall(sjson.decode, file.getcontents(f));
if status then
return obj;
else
return {};
end
end
_.f.write = function(f, obj)
local status, json = pcall(sjson.encode, obj);
if status then
return file.putcontents(f, json);
else
return false;
end
return hash
end,
push = function(hash, s)
w._push(hash, s)
func.jsonfPush('func.json', hash, s)
return hash
end,
pull = function(hash)
w.f[hash] = nil
func.jsonfPull('func.json', hash)
w.refresh()
end,
clear = function()
func.jsonfClear('func.json')
w.refresh()
end,
start = function()
print('w starting...')
local usr = func.jsonfRead('func.json')
if next(usr) ~= nil then
print('in usr')
for k, v in pairs(usr) do
print(k)
w._push(k, v)
end
--ns
_.ns.set = function(obj)
return _.f.write(_.config.v.fs.prefix.system.._.config.v.fs.filename.nsmap, obj);
end
_.ns.get = function()
return _.f.read(_.config.v.fs.prefix.system.._.config.v.fs.filename.nsmap);
end
_.ns.render = function(nid)
for local k, v in pairs(_.ns.get()) do
if k == nid and v then
return v;
end
end
return nid;
end
_.ns.exist = function(nid)
if _.ns.render(nid) == nid then
return false;
else
print('in systemd')
local systemd = func.jsonfRead('FUNC.json')
for k, v in pairs(systemd) do
print(k)
w.push(k, v)
return true;
end
end
_.ns.check = function(nid, ip, cb--[[func(bool status)]])
http.post('http://'..ip.._.config.v.http.api.discover, nil, '', function(code, data)
if code ~= 200 or data ~= nid then
cb(false);
else
cb(true);
end
end);
end
_.ns.verify = function()
local ns = _.ns.get();
for k, v in pairs(ns) do
_.ns.check(k, v, function(status)
if not status then
ns[k] = false;
_.ns.set(ns);
end
end)
end
end
--package
_.package.pack = function(o)
local status, json = pcall(sjson.encode, o);
if status then
return json;
else
return nil;
end
end
_.package.depack = function(s)
local status, obj = pcall(json.decode, s);
if status then
return obj;
else
return {};
end
end
_.package.set = function(to--[[nid]], body--[[obj]], mode)
local o = {
from = _.config.v.nid,
to = to,
mode = mode,
body = body
}
return _.package.pack(o);
end
_.package.get = function(pack--[[string package]])
local status, obj = pcall(json.decode, pack);
if status and obj.from and obj.mode then
return obj.from, obj.body, obj.mode;
else
return nil, nil, nil;
end
if func.tableKeyExist(w.f, 'construct') then
w.f:construct()
end
--db
_.db.toIndex = function(key)
return encoder.toBase64(key);
end
_.db.fromIndex = function(index)
return encoder.fromBase64(index);
end
_.db.getFileName = function(key)
return _.config.v.fs.prefix.data.._.db.toIndex(key);
end
_.db.public.keys = function() --list all keys with size
local o = {};
for local k, v in pairs(file.list(_.config.v.fs.prefix.data..'.')) do
o[_.db.fromIndex(k)] = v;
end
end,
stop = function()
if func.tableKeyExist(w.f, 'destruct') then
w.f:destruct()
return o;
end
_.db.public.get = function(key)
return _.f.read();
end
_.db.public.set = function(key, obj)
return _.f.write(_.db.getFileName(key), obj);
end
_.db.public.del = function(key)
local fileName = _.db.getFileName(key);
file.remove(fileName);
return ~file.exists(fileName);
end
_.db.public.clear = function()
local flag = true;
for local k, v in pairs(_.db.public.keys()) do
flag = flag and _.db.public.del(k);
end
w.f = {}
collectgarbage("collect")
end,
refresh = function()
pcall(w.stop)
pcall(w.start)
end
}
return flag;
end
--Functions
func = {
init = {
run = function()
if file.exists("__running") then
file.rename("__running", "__stopped")
--msg
_.msg.dpost = function(to, name, body, cb--[[(bool status, data)]])
if _.ns.exist(to) then
http.post(
'http://'.._.ns.render(to)..'/msg/'..encoder.toBase64(name),
'Content-Type: application/json\r\n',
_.package.set(to, body, 'post'),
function(code, res)
if code ~= 200 then
cb(false);
else
cb(true, _.package.get(res));
end
end
);
else
cb(false);
end
end
_.msg.dsend = function(to, name, body)
if _.ns.exist(to) then
http.post(
'http://'.._.ns.render(to)..'/msg/'..encoder.toBase64(name),
'Content-Type: application/json\r\n',
_.package.set(to, body, 'send'),
function(code, res) end
);
end
end
_.msg.mpost = function(to, name, body, cb)
_.msg.postWaitList[encoder.toBase64(name)..to] = false;
local PostBeginAt = tmr.time();
_.timer.setInterval(function(delay)
if _.msg.postWaitList[encoder.toBase64(name)..to] ~= false then
cb(true, _.msg.postWaitList[encoder.toBase64(name)..to]);
_.msg.postWaitList[encoder.toBase64(name)..to] = nil;
delay(-1);
else
func.jsonfClear('func.json')
if PostBeginAt < tmr.time() - _.config.v.mqtt.PostTimeout then
cb(false);
_.msg.postWaitList[encoder.toBase64(name)..to] = nil;
delay(-1);
end
end
collectgarbage("collect")
w.start()
collectgarbage("collect")
func.init.wifi(func.init.udp, func.init.w, func.run)
end,
wifi = function(after, after2, after3)
print('Setting up WIFI...')
wifi.setmode(wifi.STATION)
wifi.sta.config(CONFIG.wifi.station)
wifi.sta.connect()
local wifiInit = tmr.create()
wifiInit:register(1000, tmr.ALARM_AUTO, function()
if wifi.sta.getip() == nil then
print('Waiting for IP ...')
else
print('IP is ' .. wifi.sta.getip())
wifiInit:unregister()
after(after2, after3)
end
end)
wifiInit:start()
end,
udp = function (after, after2)
udp = net.createUDPSocket()
udp:listen(CONFIG.udp.server.port)
udp:on("receive", w.receive)
after(after2)
end,
w = function(after)
w.heartbeat()
local heartbeat = tmr.create()
heartbeat:register(CONFIG.w.heartbeat.interval, tmr.ALARM_AUTO, function()
w.heartbeat()
file.rename("__stopped", "__running")
end);
heartbeat:start()
if after then after() end
end, _.config.v.mqtt.PostCheckInterval);
_.mqtt.v:publish(
_.config.v.mqtt.topicPrefix..to..'/'..encoder.toBase64(name),
_.package.set(to, body, 'post'),
1,
0
);
end
_.msg.msend = function(to, name, body)
_.mqtt.v:publish(
_.config.v.mqtt.topicPrefix..to..'/'..encoder.toBase64(name),
_.package.set(to, body, 'send'),
0,
0
);
end
_.msg.public.onSend = function(name, f--[[(body, from)]])
_.msg.reg.send[encoder.toBase64(name)] = f;
end
_.msg.public.onPost = function(name, f--[[body, from, reply(reply_body)]])
_.msg.reg.post[encoder.toBase64(name)] = f;
end
_.msg.public.send = function(to, name, body)
if _.ns.exist(to) then
_.msg.dsend(to, name, body);
else
_.msg.msend(to, name, body);
end
},
randomLetter = function(len)
local rt = ""
for i = 1, len, 1 do
rt = rt..string.char(math.random(97,122))
end
return rt
end,
jsonfRead = function(f)
if file.open(f) then
local status, obj = pcall(sjson.decode, file.read())
file.close()
if status then
return obj
else
return {}
end
end
_.msg.public.post = function(to, name, body, cb)
if _.ns.exist(to) then
_.msg.dpost(to, name, body, cb);
else
_.msg.mpost(to, name, body, cb);
end
end
--api
_.api.http.discover = function(res)
res.finish(_.config.v.nid, 200);
end
_.api.http.msg = function(name, req, res)
local data = '';
req.ondata = function(req, chunk)
if chunk ~= nil then
data = data..chunk;
else
local from, body, mode = _.package.get(data);
if mode == 'send' then
res.finish();
for k, v in pairs(_.msg.reg.send) do
if k == name then
v(body, from);
return;
end
end
elseif mode == 'post' then
for k, v in pairs(_.msg.reg.post) do
if k == name then
v(body, from, function(reply_body)
res.finish(_.package.set(from, reply_body, 'reply'));
end);
return;
end
end
res.finish(nil, 404);
end
end
end
end
_.api.mqtt.msg = function(name, data)
local from, body, mode = _.package.get(data);
if mode == 'send' then
for k, v in pairs(_.msg.reg.send) do
if k == name then
v(body, from);
return;
end
end
elseif mode == 'post' then
for k, v in pairs(_.msg.reg.post) do
if k == name then
v(body, from, function(reply_body)
_.mqtt.v:publish(_.config.v.mqtt.topicPrefix..from..'/msg/'..name.._.config.v.nid, _.package.set(from, reply_body, 'reply'), 1, 0);
end);
return;
end
end
elseif mode == 'reply' then
for k, v in pairs(_.msg.postWaitList) do
if k == name then
_.msg.postWaitList[k] = body;
return;
end
end
end
return {}
end,
jsonfWrite = function(f, obj)
if file.open(f, 'w+') then
local status, json = pcall(sjson.encode, obj)
if status then
file.write(json)
else
file.write("{}")
end
file.close()
end
_.api.mqtt.heartbeat = function()
local o = {
nid = _.config.v.nid,
uptime = tmr.time(),
heap = node.heap(),
funcID = _.func.id,
ip = wifi.sta.getip(),
ns = _.ns.get()
}
_.mqtt.v:publish(_.mqtt.getTopic('heartbeat'), _.package.pack(o), 0, 0);
end
_.api.mqtt.ns = function(data)
local obj = _.package.depack(data);
_.ns.set(obj);
end
_.api.mqtt.func = function(data)
local obj = _.package.depack(data);
_.f.write(_.config.v.fs.prefix.system.._.config.v.fs.filename.func, obj);
_._.restart();
end
_.api.mqtt.restart = function()
_._.restart();
end
--Environment Loading & Checking
----------------------
--Config Checking
_.config.v = _.f.read(_.config.path);
_.table.merge(_.config.v, _.config.default);
--Flag Checking
_.flag.load();
if _.flag.v == nil then
_.flag.set(0);
end
--User Func Checking
local func = _.f.read(_.config.v.fs.prefix.system.._.config.v.fs.filename.func);
if func and func.id and func.offline and func.online then
_.func.id = func.id;
_.func.offline = func.offline;
_.func.online = func.online;
end
func = nil;
--System Preparation
--------------------
--Signal Start
_.signal.init();
_.signal.set(1500);
--Decide System Mode
_.flag.set(_.flag.v + 1);
if _.flag.v >= _.config.v.flag.MaxRetryTimes and _.flag.v <= _.config.v.flag.MaxRetryTimes + _.config.v.flag.MaxResetTimes then
_._.reset();
elseif _.flag.v > _.config.v.flag.MaxRetryTimes + _.config.v.flag.MaxResetTimes then
--safe mode
--Signal set
_.signal.set(3000);
do return end;
end
--OFFLINE System Launch
-----------------------
--Signal set
_.signal.set(800);
--Run user offline func
_.flag.ward(function()
tmr.softwd(_.config.v.func.offline.MaxWaitTime); --start watchdog
if not __run(_.func.offline, _.timer, _.db.public, nil)--[[enable DB and disable MSG]] then
_._.restart('Offline Func Startup Fail..');
end
end,
jsonfPush = function(f, hash, s)
local obj = func.jsonfRead(f)
obj[hash] = s
func.jsonfWrite(f, obj)
end,
jsonfPull = function(f, hash)
func.jsonfPush(f, hash, nil)
end,
jsonfClear = function(f)
func.jsonfWrite(f, {})
end,
encrypt = function(s, kay)
if key == nil then return s;end
local msg = encoder.toHex(crypto.encrypt("AES-ECB", key, s..func.randomLetter(4)))
return msg..string.sub(encoder.toHex(crypto.hmac("sha1", msg, key)), 1, 8)
end,
decrypt = function(s, kay)
if key == nil then return s;end
local msg, hmac = string.sub(s, 1, string.len(s)-8), string.sub(s, string.len(s)-7, 8)
if string.sub(encoder.toHex(crypto.hmac("sha1", msg, key)), 1, 8) ~= hmac then return nil; end
local raw = crypto.decrypt("AES-ECB", key, encoder.fromHex(msg))
return string.sub(raw, 1, string.len(raw) - 4)
end,
tableKeyExist = function(obj, key)
for k, v in pairs(obj) do
if k == key then
return true
end
end
return false
end
}
tmr.softwd(-1); --disable watchdog
end);
--Run
func.run = function()
--run content
gpio.write(0, gpio.LOW)
end
--Network Modules Init
----------------------
--If OFFLINEONLY is configed, do not start network
if _.config.v.offlineOnly == true then
return;
end
--Signal set
_.signal.set(200);
--Connect to wifi AP
wifi.setmode(wifi.STATION);
wifi.sta.sethostname('WIOT-'.._.config.v.nid);
wifi.sta.config(_.config.v.wifi.config);
_.timer.setInterval(function(delay)
if wifi.sta.getip() ~= nil then
delay(-1);
_.init.http();
_.init.mqtt();
end
end, _.config.v.wifi.CheckInterval);
--Load CONFIG
CONFIG = func.jsonfRead('config.json')
--http module
_.init.http = function()
_.http.v = httpserver.createServer(_.config.v.http.port, function(req, res)
local path = string.split(req.url, '/');
if path[2] == 'discover' then
_.api.http.discover(res);
elseif path[2] == 'msg' and path[3] then
_.api.http.msg(path[3], req, res);
else
res.finish('', 500);
end
end);
end
--exec Init
func.init.run()
--mqtt module
_.init.mqtt = function()
_.mqtt.v = mqtt.Client(_.config.v.nid, _.config.v.mqtt.keepaliveTimer, _.config.v.mqtt.user, _.config.v.mqtt.password);
_.mqtt.v:lwt(_.mqtt.getTopic('status'), 'offline', 0, 0);
_.mqtt.v:on('offline', function()
_.timer.setTimeout(_.mqtt.start, _.config.v.mqtt.OfflineRetryInterval);
end);
_.mqtt.v:on('message', function(client, topic, data)
local path = string.split(string.split(topic, _.config.v.mqtt.topicPrefix), '/');
if path[1] == 'ctl' then
if path[2] == 'heartbeat' then
_.api.mqtt.heartbeat();
elseif path[2] == 'ns' then
_.api.mqtt.ns(data);
elseif path[2] == 'func' then
_.api.mqtt.func(data);
elseif path[2] == 'restart' then
_.api.mqtt.restart();
end
elseif path[1] == 'msg' and path[2] then
_.api.mqtt.msg(path[2], data);
end
end);
end
--ONLINE System Launch
----------------------
--Run user offline func
_.init.onlineFunc = function()
_.flag.ward(function()
tmr.softwd(_.config.v.func.online.MaxWaitTime); --start watchdog
if not __run(_.func.online, _.timer, _.db.public, _.msg.public)--[[enable DB and MSG]] then
_._.restart('online Func Startup Fail..');
end
tmr.softwd(-1); --disable watchdog
_.signal.destroy(); --destroy signal
end);
end
end)(function(func, timer, db, msg)
return pcall(loadstring(func));
end);

@ -0,0 +1,271 @@
--Global Var
CONFIG = {}
udp = nil --UDP Server
key = nil --Encrypt Key
G = {} --Var Zone
--wIoT Toolbox
w = {
f = {},
waitList = {},
send = function(ip, port, fid, body, cb)
local sid = func.randomLetter(8)
local o = {
fid = fid,
sid = sid,
id = CONFIG.w.id,
body = body
}
local status, msg = pcall(sjson.encode, o)
udp:send(port, ip, msg)
if cb == nil then return ;end
w.waitList[sid] = false
local resTimer = tmr.create()
local retryTimer = tmr.create()
local retryTimes = CONFIG.w.maxRetryTimes
resTimer:register(CONFIG.w.scanInterval, tmr.ALARM_AUTO, function()
if func.tableKeyExist(w.waitList, sid) and w.waitList[sid] ~= false then
cb(w.waitList[sid])
w.waitList[sid] = nil
resTimer:unregister()
retryTimer:unregister()
collectgarbage("collect")
end
end)
retryTimer:register(CONFIG.w.retryInterval, tmr.ALARM_AUTO, function()
if retryTimes > 0 and func.tableKeyExist(w.waitList, sid) and w.waitList[sid] == false then
udp:send(port, ip, msg)
retryTimes = retryTimes - 1
else
retryTimer:unregister()
collectgarbage("collect")
end
end)
resTimer:start()
retryTimer:start()
end,
receive = function(s, data, port, ip)
print(data)
local status, msg = pcall(sjson.decode, data)
if not status then return end
if not func.tableKeyExist(msg, 'sid') or not func.tableKeyExist(msg, 'body') then return end
--respond mode
print(msg.fid)
if not func.tableKeyExist(msg, 'fid') then
if func.tableKeyExist(w.waitList, msg.sid) then
w.waitList[msg.sid] = msg.body
end
return
end
print(msg.fid)
--request mode
if not func.tableKeyExist(w.f, msg.fid) then return end
local res = w.f[msg.fid](msg.body, {port = port, ip = ip, socket = s, sid = msg.sid, fid = msg.fid});
print(msg.fid)
local resObj = {
sid = msg.sid,
id = CONFIG.w.id,
body = res
}
status, res = pcall(sjson.encode, resObj)
print(res)
s:send(port, ip, res)
end,
heartbeat = function()
local o = {
version = CONFIG.firmware.version,
id = CONFIG.w.id,
ip = wifi.sta.getip(),
port = CONFIG.udp.server.port,
}
--request
print(sjson.encode(o))
udp:send(CONFIG.w.director.port, CONFIG.w.director.ip, sjson.encode(o))
end,
_push = function(hash, s)
w.f[hash] = function(r)
if hash == 'construct' or hash == 'destruct' then
print(s)
loadstring('print("hhhhhhh")')()
loadstring(s)()
return
end
local status, msg = pcall(loadstring('return '..s)(), r)
local data = {
status = status,
data = msg
}
return data
end
return hash
end,
push = function(hash, s)
w._push(hash, s)
func.jsonfPush('func.json', hash, s)
return hash
end,
pull = function(hash)
w.f[hash] = nil
func.jsonfPull('func.json', hash)
w.refresh()
end,
clear = function()
func.jsonfClear('func.json')
w.refresh()
end,
start = function()
print('w starting...')
local usr = func.jsonfRead('func.json')
if next(usr) ~= nil then
print('in usr')
for k, v in pairs(usr) do
print(k)
w._push(k, v)
end
else
print('in systemd')
local systemd = func.jsonfRead('FUNC.json')
for k, v in pairs(systemd) do
print(k)
w.push(k, v)
end
end
if func.tableKeyExist(w.f, 'construct') then
w.f:construct()
end
end,
stop = function()
if func.tableKeyExist(w.f, 'destruct') then
w.f:destruct()
end
w.f = {}
collectgarbage("collect")
end,
refresh = function()
pcall(w.stop)
pcall(w.start)
end
}
--Functions
func = {
init = {
run = function()
if file.exists("__running") then
file.rename("__running", "__stopped")
else
func.jsonfClear('func.json')
end
collectgarbage("collect")
w.start()
collectgarbage("collect")
func.init.wifi(func.init.udp, func.init.w, func.run)
end,
wifi = function(after, after2, after3)
print('Setting up WIFI...')
wifi.setmode(wifi.STATION)
wifi.sta.config(CONFIG.wifi.station)
wifi.sta.connect()
local wifiInit = tmr.create()
wifiInit:register(1000, tmr.ALARM_AUTO, function()
if wifi.sta.getip() == nil then
print('Waiting for IP ...')
else
print('IP is ' .. wifi.sta.getip())
wifiInit:unregister()
after(after2, after3)
end
end)
wifiInit:start()
end,
udp = function (after, after2)
udp = net.createUDPSocket()
udp:listen(CONFIG.udp.server.port)
udp:on("receive", w.receive)
after(after2)
end,
w = function(after)
w.heartbeat()
local heartbeat = tmr.create()
heartbeat:register(CONFIG.w.heartbeat.interval, tmr.ALARM_AUTO, function()
w.heartbeat()
file.rename("__stopped", "__running")
end);
heartbeat:start()
if after then after() end
end
},
randomLetter = function(len)
local rt = ""
for i = 1, len, 1 do
rt = rt..string.char(math.random(97,122))
end
return rt
end,
jsonfRead = function(f)
if file.open(f) then
local status, obj = pcall(sjson.decode, file.read())
file.close()
if status then
return obj
else
return {}
end
end
return {}
end,
jsonfWrite = function(f, obj)
if file.open(f, 'w+') then
local status, json = pcall(sjson.encode, obj)
if status then
file.write(json)
else
file.write("{}")
end
file.close()
end
end,
jsonfPush = function(f, hash, s)
local obj = func.jsonfRead(f)
obj[hash] = s
func.jsonfWrite(f, obj)
end,
jsonfPull = function(f, hash)
func.jsonfPush(f, hash, nil)
end,
jsonfClear = function(f)
func.jsonfWrite(f, {})
end,
encrypt = function(s, kay)
if key == nil then return s;end
local msg = encoder.toHex(crypto.encrypt("AES-ECB", key, s..func.randomLetter(4)))
return msg..string.sub(encoder.toHex(crypto.hmac("sha1", msg, key)), 1, 8)
end,
decrypt = function(s, kay)
if key == nil then return s;end
local msg, hmac = string.sub(s, 1, string.len(s)-8), string.sub(s, string.len(s)-7, 8)
if string.sub(encoder.toHex(crypto.hmac("sha1", msg, key)), 1, 8) ~= hmac then return nil; end
local raw = crypto.decrypt("AES-ECB", key, encoder.fromHex(msg))
return string.sub(raw, 1, string.len(raw) - 4)
end,
tableKeyExist = function(obj, key)
for k, v in pairs(obj) do
if k == key then
return true
end
end
return false
end
}
--Run
func.run = function()
--run content
gpio.write(0, gpio.LOW)
end
--Load CONFIG
CONFIG = func.jsonfRead('config.json')
--exec Init
func.init.run()

@ -0,0 +1,15 @@
var packageRoot = require.resolve('nodemcu-tool')
.match(/^.*[\/\\]node_modules[\/\\][^\/\\]*/)[0];
console.log(packageRoot)
;(async ()=>{
var _connector = require('nodemcu-tool');
console.log(await _connector.connect('COM3'))
console.log('dd')
console.log(await _connector.upload('test/led.lua', 'led.lua.', {minify: true}, ()=>{}))
await _connector.disconnect();
})();
//
Loading…
Cancel
Save