You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
8.7 KiB
Lua
250 lines
8.7 KiB
Lua
-- PrivateRouter Easy Mesh
|
|
|
|
local m,s,o
|
|
local sys = require "luci.sys"
|
|
local uci = require "luci.model.uci".cursor()
|
|
local iwinfo = require "iwinfo"
|
|
|
|
m = Map("easymesh",
|
|
translate("Easy Mesh WiFi Setup"),
|
|
translate("Powered by Batman-adv (Better Approach To Mobile Adhoc Networking - Advanced). First setup your Mesh Gateway Server then setup the nodes. When configuring a Mesh Node, first activate your mesh WiFi on the radio device and establish a connection. Then enable it as a DHCP node. The default settings are typically adequate for most Mesh WiFi configurations.")
|
|
.. "<br/>" .. translate("Official website:") .. ' <a href="https://www.open-mesh.org/projects/batman-adv/wiki" target="_blank">https://www.open-mesh.org/projects/batman-adv/wiki</a>'
|
|
)
|
|
|
|
|
|
function detect_Node()
|
|
local data = {}
|
|
local lps = luci.util.execi(" batctl n 2>/dev/null | tail +2 | sed 's/^[ ][ ]*//g' | sed 's/[ ][ ]*/ /g' | sed 's/$/ /g' ")
|
|
for value in lps do
|
|
local row = {}
|
|
local pos = string.find(value, " ")
|
|
local IFA = string.sub(value, 1, pos - 1)
|
|
local value = string.sub(value, pos + 1, string.len(value))
|
|
pos = string.find(value, " ")
|
|
local pos = string.find(value, " ")
|
|
local Neighbora = string.sub(value, 1, pos - 1)
|
|
local value = string.sub(value, pos + 1, string.len(value))
|
|
pos = string.find(value, " ")
|
|
local pos = string.find(value, " ")
|
|
local lastseena = string.sub(value, 1, pos - 1)
|
|
local value = string.sub(value, pos + 1, string.len(value))
|
|
pos = string.find(value, " ")
|
|
row["IF"] = IFA
|
|
row["Neighbor"] = Neighbora
|
|
row["lastseen"] = lastseena
|
|
table.insert(data, row)
|
|
end
|
|
return data
|
|
end
|
|
|
|
function get_verbose_hw_info(iface)
|
|
local type = iwinfo.type(iface)
|
|
if not type then
|
|
return "Unknown interface"
|
|
end
|
|
|
|
local driver = iwinfo[type]
|
|
if not driver then
|
|
return "Driver not supported"
|
|
end
|
|
|
|
local hw_name = driver.hardware_name and driver.hardware_name(iface)
|
|
if not hw_name or hw_name == "" then
|
|
hw_name = "Unknown hardware"
|
|
end
|
|
|
|
local hw_modes = driver.hwmodelist and driver.hwmodelist(iface)
|
|
local supported_modes = {}
|
|
if hw_modes then
|
|
for mode, supported in pairs(hw_modes) do
|
|
if supported then
|
|
table.insert(supported_modes, mode)
|
|
end
|
|
end
|
|
end
|
|
|
|
if #supported_modes == 0 then
|
|
supported_modes_str = "No mode information"
|
|
else
|
|
supported_modes_str = table.concat(supported_modes, "/")
|
|
end
|
|
|
|
local verbose_info = hw_name .. " (" .. supported_modes_str .. ")"
|
|
return verbose_info
|
|
end
|
|
|
|
local Nodes = luci.sys.exec("batctl n 2>/dev/null| tail +3 | wc -l")
|
|
local Node = detect_Node()
|
|
v = m:section(Table, Node, "" ,"<b>" .. translate("Active node") .. "" .. Nodes .. "</b>")
|
|
v:option(DummyValue, "IF", translate("IF"))
|
|
v:option(DummyValue, "Neighbor", translate("Neighbor"))
|
|
v:option(DummyValue, "lastseen", translate("lastseen"))
|
|
|
|
-- Basic
|
|
s = m:section(TypedSection, "easymesh", translate("Mesh Gateway & Node WiFi Settings"), translate("Choose Mesh Gateway or Mesh Node WiFi Settings: Begin by completing this section on your mesh server and nodes. Ensure each radio's WiFi network name is consistent. For example: easymesh_AC, easymesh_N."))
|
|
s.anonymous = true
|
|
|
|
-- Connection Type Dropdown
|
|
--o = s:option(ListValue, "backbone", translate("Connection Type"), translate("Choose if Node or Gateway is connected to internet by LAN or WiFi"))
|
|
--o:value("lan", translate("LAN"))
|
|
--o:value("wifi", translate("WiFi"))
|
|
--o.default = "lan"
|
|
--o.rmempty = false
|
|
|
|
-- AP Name
|
|
--apn = s:option(Value, "apname", translate("AP Name"), translate("Enter the client WiFi AP name"))
|
|
--apn:depends("backbone", "wifi")
|
|
--apn.placeholder = "easymesh_AC"
|
|
--apn.rmempty = true
|
|
|
|
-- AP Password
|
|
--app = s:option(Value, "appass", translate("AP Password"), translate("Enter the client WiFi AP password"))
|
|
--app:depends("backbone", "wifi")
|
|
--app.password = true
|
|
--app.placeholder = "easymesh"
|
|
--app.rmempty = true
|
|
|
|
s:tab("setup", translate("Basic Setup"))
|
|
s:tab("apmode", translate("AP Mode"))
|
|
s:tab("advanced", translate("Advanced Settings"))
|
|
|
|
---- Eanble
|
|
o = s:taboption("setup", Flag, "enabled", translate("Enable"))
|
|
o.default = 0
|
|
o.rmempty = false
|
|
|
|
|
|
-- Move basic settings under the "Setup" tab
|
|
o = s:taboption("setup", ListValue, "role", translate("Mesh Mode"))
|
|
o:value("off", translate("Node"))
|
|
o:value("server", translate("Server"))
|
|
--o:value("client", translate("Client (advanced)"))
|
|
o:depends("enabled", 1)
|
|
o.rmempty = false
|
|
|
|
apRadio = s:taboption("setup", MultiValue, "apRadio", translate("Mesh Radio(s)"))
|
|
|
|
uci:foreach("wireless", "wifi-device",
|
|
function(s)
|
|
local iface = s['.name']
|
|
local hw_modes = get_verbose_hw_info(iface)
|
|
local desc = string.format("%s (%s)", iface, hw_modes)
|
|
apRadio:value(iface, desc) -- Display radio interface with its hardware modes
|
|
end)
|
|
apRadio.default = "radio0"
|
|
apRadio:depends("enabled", 1)
|
|
apRadio.rmempty = false
|
|
apRadio.widget = "select"
|
|
|
|
o = s:taboption("setup", Value, "mesh_id", translate("Mesh SSID"))
|
|
o.default = "easymesh_AC"
|
|
o:depends("enabled", 1)
|
|
|
|
encryption = s:taboption("setup", Flag, "encryption", translate("Encryption WIP DROPDOWN"), translate(""))
|
|
encryption.default = 0
|
|
encryption.rmempty = false
|
|
encryption:depends("enabled", 1)
|
|
|
|
o = s:taboption("setup", Value, "key", translate("Mesh Password"))
|
|
o.default = "easymesh"
|
|
o:depends({enabled = "1", encryption = "1"})
|
|
o.password = true
|
|
|
|
-- Move K/V/R settings to the "Advanced" tab
|
|
enable_kvr = s:taboption("advanced", Flag, "kvr", translate("K/V/R"), translate("Enable Key Value Roaming"))
|
|
enable_kvr.default = 1
|
|
enable_kvr.rmempty = false
|
|
|
|
mobility_domain = s:taboption("advanced", Value, "mobility_domain", translate("Mobility Domain"), translate("4-character hexadecimal ID"))
|
|
mobility_domain.default = "4f57"
|
|
--mobility_domain.datatype = "and(hexstring,rangelength(4,4))"
|
|
mobility_domain:depends("kvr", 1)
|
|
|
|
rssi_val = s:taboption("advanced", Value, "rssi_val", translate("Threshold for a good RSSI"))
|
|
rssi_val.default = "-60"
|
|
--rssi_val.datatype = "range(-1,-120)"
|
|
rssi_val:depends("kvr", 1)
|
|
|
|
low_rssi_val = s:taboption("advanced", Value, "low_rssi_val", translate("Threshold for a bad RSSI"))
|
|
low_rssi_val.default = "-88"
|
|
--low_rssi_val.datatype = "range(-1,-120)"
|
|
low_rssi_val:depends("kvr", 1)
|
|
|
|
|
|
---- Apply MESH settings
|
|
--ctrl = m:section(TypedSection, "easymesh", "Apply Mesh WiFi Settings to Server or Node")
|
|
--ctrl.anonymous = true
|
|
--ctrl.addremove = false
|
|
|
|
----btnStop = ctrl:option(Button, "_btn_start", translate("Apply Mesh WiFi Settings"))
|
|
--function btnStop.write()
|
|
-- io.popen("/etc/init.d/easymesh start")
|
|
--end
|
|
|
|
---- 802.11F
|
|
--enable = s:option(Flag, "iapp", translate("inter-access point protocol"), translate("Wireless Access Points (APs) running on different vendors can communicate with each other"))
|
|
--enable.default = 0
|
|
--enable.rmempty = false
|
|
|
|
-- NodeMode
|
|
-- s = m:section(TypedSection, "easymesh", translate("Enable Router as DHCP Mesh Node"), translate("Set up Easy Mesh WiFi on your server and nodes first. All mesh nodes will utilize your mesh server for DHCP. "))
|
|
-- s.anonymous = true
|
|
|
|
---- ap_mode
|
|
o = s:taboption("apmode", Value, "hostname", translate("Node Hostname"))
|
|
o.default = "node2"
|
|
o:value("node2", "node2")
|
|
o:value("node3", "node3")
|
|
o:value("node4", "node4")
|
|
o:value("node5", "node5")
|
|
o:value("node6", "node6")
|
|
o:value("node7", "node7")
|
|
o:value("node8", "node8")
|
|
o:value("node9", "node9")
|
|
o.datatype = "string"
|
|
o:depends("role", "off")
|
|
|
|
btnAPMode = s:taboption("apmode", Button, "_btn_apmode", translate("Join Mesh Network"), translate("WARNING: THIS WILL CHANGE THIS NODE'S IP ADDRESS, YOU WILL LOOSE ACCESS TO THIS UI"))
|
|
function btnAPMode.write()
|
|
io.popen("/easymesh/easymesh.sh dumbap &")
|
|
end
|
|
btnAPMode:depends("role", "off")
|
|
---- ip address
|
|
--o = s:option(Value, "ipaddr", translate("Static IP Address"))
|
|
--o.default = "192.168.8.2"
|
|
--o.datatype = "ip4addr"
|
|
--o:depends("ap_mode", 1)
|
|
|
|
-- o = s:option(Value, "dns", translate("Mesh Gateway IP Address"))
|
|
-- o.default = "192.168.8.1"
|
|
-- o.datatype = "ip4addr"
|
|
-- o:depends("ap_mode", 1)
|
|
|
|
-- o = s:option(Value, "netmask", translate("IPv4 netmask"))
|
|
-- o.default = "255.255.255.0"
|
|
-- o.datatype = "ip4addr"
|
|
-- o:depends("ap_mode", 1)
|
|
|
|
-- MESH Node Control: apply mesh settings
|
|
ctrl = m:section(TypedSection, "easymesh", "Click Save Then Enable or Disable Your Mesh WiFi settings")
|
|
ctrl.anonymous = true
|
|
ctrl.addremove = false
|
|
|
|
|
|
function m.on_after_commit(self)
|
|
local enabled = m:formvalue("cbid.easymesh.easymesh.enabled")
|
|
if enabled and enabled == "1" then
|
|
luci.sys.call("/easymesh/easymesh.sh &")
|
|
else
|
|
luci.sys.call("/easymesh/easymesh.sh &")
|
|
end
|
|
end
|
|
|
|
function o.write(self, section, value)
|
|
Flag.write(self, section, value)
|
|
-- Run init start
|
|
-- luci.sys.call("uci commit")
|
|
-- luci.sys.call("/etc/init.d/easymesh start &")
|
|
end
|
|
|
|
return m |