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.

231 lines
9.6 KiB
Lua

-- PrivateRouter Easy Mesh
1 year ago
local m,s,o
local sys = require "luci.sys"
local uci = require "luci.model.uci".cursor()
local iwinfo = require "iwinfo"
1 year ago
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>'
)
1 year ago
function detect_Node()
local data = {}
-- Streamline the command to retrieve node information
local lps = luci.util.execi("batctl n 2>/dev/null | tail +2 | sed 's/^[ ]*//;s/[ ]*/ /g'")
for line in lps do
-- Split the line into parts using pattern matching
local ifa, neighbor, lastseen = string.match(line, "(%S+) (%S+) (%S+)")
if ifa and neighbor and lastseen then
-- Construct the row and add it to the data table
local row = {["IF"] = ifa, ["Neighbor"] = neighbor, ["lastseen"] = lastseen}
table.insert(data, row)
end
end
return data
1 year ago
end
10 months ago
function get_verbose_hw_info(iface)
local type = iwinfo.type(iface)
if not type then
return "Generic"
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
10 months ago
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
10 months ago
end
if #supported_modes == 0 then
supported_modes_str = "No mode information"
else
10 months ago
supported_modes_str = table.concat(supported_modes, "/")
end
10 months ago
local verbose_info = hw_name .. " (" .. supported_modes_str .. ")"
return verbose_info
end
1 year ago
local Nodes = luci.sys.exec("batctl n 2>/dev/null| tail +3 | wc -l")
local Node = detect_Node()
v = m:section(Table, Node, translate("Active Nodes") ,"<b>" .. translate("Number of Active Nodes: ") .. Nodes .. "</b>")
v:option(DummyValue, "IF", translate("Interface"))
v:option(DummyValue, "Neighbor", translate("Neighbor Nodes"))
v:option(DummyValue, "lastseen", translate("Last Seen Timestamp"))
1 year ago
-- Basic
s = m:section(TypedSection, "easymesh", translate("Mesh Settings"))
1 year ago
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"))
10 months ago
s:tab("apmode", translate("AP Mode"))
s:tab("advanced", translate("Advanced Settings"))
10 months ago
---- Eanble
o = s:taboption("setup", Flag, "enabled", translate("Enable Mesh Network"), translate("Toggle this switch to activate or deactivate the Mesh Network on this device according to the settings specified in this configuration. Make sure to configure all necessary settings before enabling the Mesh Network. Changes will apply when you click Save and Apply"))
10 months ago
o.default = 0
10 months ago
-- Move basic settings under the "Setup" tab
o = s:taboption("setup", ListValue, "role", translate("Mesh Mode"), translate('<p style="text-align: justify; padding: 0;"><strong>Choose the role this device will play in your mesh network. There are two options available:</strong></p> <p style="text-align: justify; padding: 0;"><strong>1. Server:</strong> If you select this option, this device will act as the Mesh Gateway Server. The server manages the routing of data in the network and handles connections to the internet. It is the central point of your mesh network.</p> <p style="text-align: justify; padding: 0;"><strong>2. Node:</strong> The device functions as a Mesh Node if this option is selected. Nodes connect to the Mesh Gateway Server and other nodes to extend the range of the network. Nodes can also route traffic between each other to increase network efficiency.</p> <p style="text-align: justify; padding: 0;"><strong>Remember to set up the Mesh Gateway Server first before setting up the nodes.</strong></p>'))
o:value("server", translate("Server"))
o:value("off", translate("Node"))
o.default = "server"
--o:value("client", translate("Client (advanced)"))
1 year ago
apRadio = s:taboption("setup", MultiValue, "apRadio", translate("Mesh Radio(s)"), translate('<p style="text-align: justify; padding: 0;">Select one or multiple radio interfaces to be used for the mesh network. Each selected radio interface will be configured to participate in the mesh network, extending its range and improving its resilience. By using multiple radios, your mesh network can balance the network load and handle a larger number of connected devices.</p>'))
1 year ago
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"
10 months ago
apRadio.widget = "select"
1 year ago
o = s:taboption("setup", Value, "mesh_id", translate("Mesh SSID"))
o.default = "easymesh_AC"
1 year ago
encryption = s:taboption("setup", Flag, "encryption", translate("Enable Password"), translate(""))
10 months ago
encryption.default = 0
1 year ago
o = s:taboption("setup", Value, "key", translate("Mesh Password"))
1 year ago
o.default = "easymesh"
o:depends("encryption", 1)
10 months ago
o.password = true
1 year ago
enable_kvr = s:taboption("advanced", Flag, "kvr", translate("K/V/R"), translate("Enable Key Value Roaming"))
enable_kvr.default = 1
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))"
rssi_val = s:taboption("advanced", Value, "rssi_val", translate("Threshold for a good RSSI"))
rssi_val.default = "-60"
--rssi_val.datatype = "range(-1,-120)"
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)"
1 year ago
---- 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
1 year ago
---- 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
10 months ago
-- 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
1 year ago
---- ap_mode
10 months ago
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"
10 months ago
o:depends("role", "off")
-- IP Mode (DHCP or Static)
ipmode = s:taboption("apmode", ListValue, "ipmode", translate("IP Mode"), translate("Choose if the node uses DHCP or a Static IP"))
ipmode:value("dhcp", translate("DHCP"))
ipmode:value("static", translate("Static"))
ipmode.default = "dhcp"
ipmode:depends("role", "off")
-- Static IP address
o = s:taboption("apmode", Value, "ipaddr", translate("Static IP Address"))
o.default = "192.168.70.254"
o.datatype = "ip4addr"
o:depends({ipmode="static",role="off"})
-- DNS (Mesh Gateway IP Address)
o = s:taboption("apmode", Value, "gatewayIP", translate("Mesh Gateway IP Address"))
o.default = "192.168.70.1"
o.datatype = "ip4addr"
o:depends({ipmode="static",role="off"})
-- IPv4 netmask
o = s:taboption("apmode", Value, "netmask", translate("IPv4 netmask"))
o.default = "255.255.255.0"
o.datatype = "ip4addr"
o:depends({ipmode="static",role="off"})
btnAPMode = s:taboption("apmode", Button, "_btn_apmode", translate("Enable Dumb AP Mode"), translate("WARNING: THIS WILL CHANGE THIS NODE'S IP ADDRESS, YOU WILL LOOSE ACCESS TO THIS UI"))
10 months ago
function btnAPMode.write()
luci.sys.call("/easymesh/dumbap.sh")
10 months ago
end
btnAPMode:depends("role", "off")
1 year ago
m.on_before_apply = function(self)
local enabled = m:formvalue("cbid.easymesh.config.enabled")
if enabled and enabled == "1" then
luci.sys.call("/easymesh/easymesh.sh enable &")
else
luci.sys.call("/easymesh/easymesh.sh disable &")
end
end
return m