Thank you very much for your work. I altered this script, so it would use manual list of devices instead using DHCP, which wouldnt work always:
/www/pwol/api.lua
#!/usr/bin/lua
require("uci");
require("nixio");
require("luci.jsonc");
require("luci.http");
require("luci.ip");
--local dev_list_path = "/www/pwol/dev_list.txt";
local dev_list_json_path = "/www/pwol/dev_list.json";
function contains(arr, val) local k,v; for k,v in ipairs(arr) do if (v == val) then return true; end; end; return false; end;
function to_bool(val) if ((val == 0) or (val == nil) or (val == "")) then return false; end; return true; end;
function is_online(ip)
local ret = os.execute(string.format("ping -4 -W 1 -c 1 '%s' > /dev/nul", ip));
return not to_bool(ret);
end;
function readAll(file)
local f = assert(io.open(file, "rb"));
local content = f:read("*all");
f:close();
return content;
end
--local host_info = {}; -- { ['dev'] = { ['mac'] = '00:11:22:33:44:55', ['ip'] = "192.168.1.2" } };
--local host_info = require 'dev_list';
local host_info = luci.jsonc.parse(readAll(dev_list_json_path));
local host_ctl = {
['hl'] = function () -- host list
return host_info;
end,
['hs'] = function (host) -- host state
local ret = {};
if (host) then -- if value of 'host' is empty, return statuses of all known hosts
local info = host_info[host];
if (not info) then return nil; end;
ret[host] = info;
--print(host); -- debug
ret[host].online = is_online(info.ip);
else
for host,info in pairs(host_info) do
ret[host] = info;
ret[host].online = is_online(info.ip);
end;
end;
return ret;
end,
['hw'] = function (host) -- host wake
if (not host) then return nil; end;
local info = host_info[host];
if (not info) then return nil; end;
local ret = { [host] = host_info[host] };
ret[host].wol_ok = not to_bool(os.execute(string.format("etherwake -b -i br-lan '%s' > /dev/nul", info.mac)));
return ret;
end,
};
local args = luci.http.urldecode_params(nixio.getenv('QUERY_STRING') or arg[1] or "cmd=hl"); -- NOTE: final val is for debugging, when script executed from terminal without args, e.g. `lua api.lua 'cmd=hs&host=computer1'`
local ret = {
['ok'] = false,
-- ['args'] = args, -- DEBUG ONLY
};
repeat -- NOTE: fake loop allows shortcuts using 'break'
--local public_hosts = read_pub_hosts_list(dev_list_path); -- { 'dev1', 'dev2', ... }; // NOTE: cwd for FastCGI is '/www'
--if (not public_hosts) then ret.err = "Failed reading list of available hosts"; break; end;
--for k,v in pairs(uci.get_all('dhcp')) do --disabled
-- NOTE: current behaviour is such that only *fully* matching device host names will end up in 'host_info', others will be completely ignored
-- print(v.name); --debug
--if (contains(public_hosts, v.name)) then host_info[v.name] = { mac = v.mac, ip = v.ip }; end;
--end;
local cmd = host_ctl[args.cmd];
if (not cmd) then ret.err = "Unknown command"; break; end;
local data = cmd(args.host);
if (not data) then ret.err = "Unknown host: " .. args.host; break; end;
ret.ok = true;
ret.data = data;
until (true);
print("Status: 200 OK");
print("Content-type: application/json\n");
print(luci.jsonc.stringify(ret, '\t'));
and put devices into /www/pwol/dev_list.json.
{
"PC1": {
"mac": "11:11:11:11:11:11",
"ip": "192.168.8.12"
},
"PC2": {
"mac": "22:22:22:22:22:22",
"ip": "192.168.8.166"
},
"PC3": {
"mac": "33:33:33:33:33:33",
"ip": "192.168.8.10"
}
}
You also need to do btw if using symlink:
chmod +x /www/pwol/api.lua