luci-app-travelmate: sync with travelmate 0.9.0

* add a wireless station manager to edit and delete existing
  interfaces or scan for new uplinks

Signed-off-by: Dirk Brenken <dev@brenken.org>
This commit is contained in:
Dirk Brenken 2017-07-19 22:36:47 +02:00
parent 76b3af64c0
commit e900b892e8
8 changed files with 375 additions and 48 deletions

View file

@ -5,8 +5,8 @@ module("luci.controller.travelmate", package.seeall)
local fs = require("nixio.fs")
local util = require("luci.util")
local template = require("luci.template")
local i18n = require("luci.i18n")
local templ = require("luci.template")
function index()
if not nixio.fs.access("/etc/config/travelmate") then
@ -14,15 +14,21 @@ function index()
end
entry({"admin", "services", "travelmate"}, firstchild(), _("Travelmate"), 40).dependent = false
entry({"admin", "services", "travelmate", "tab_from_cbi"}, cbi("travelmate/overview_tab", {hideresetbtn=true, hidesavebtn=true}), _("Overview"), 10).leaf = true
entry({"admin", "services", "travelmate", "logfile"}, call("logread"), _("View Logfile"), 20).leaf = true
entry({"admin", "services", "travelmate", "stations"}, template("travelmate/stations"), _("Wireless Stations"), 20).leaf = true
entry({"admin", "services", "travelmate", "logfile"}, call("logread"), _("View Logfile"), 30).leaf = true
entry({"admin", "services", "travelmate", "advanced"}, firstchild(), _("Advanced"), 100)
entry({"admin", "services", "travelmate", "advanced", "configuration"}, cbi("travelmate/configuration_tab"), _("Edit Travelmate Configuration"), 110).leaf = true
entry({"admin", "services", "travelmate", "advanced", "cfg_wireless"}, cbi("travelmate/cfg_wireless_tab"), _("Edit Wireless Configuration"), 120).leaf = true
entry({"admin", "services", "travelmate", "advanced", "cfg_network"}, cbi("travelmate/cfg_network_tab"), _("Edit Network Configuration"), 130).leaf = true
entry({"admin", "services", "travelmate", "advanced", "cfg_firewall"}, cbi("travelmate/cfg_firewall_tab"), _("Edit Firewall Configuration"), 140).leaf = true
entry({"admin", "services", "travelmate", "wifiscan"}, template("travelmate/wifi_scan")).leaf = true
entry({"admin", "services", "travelmate", "wifiadd"}, cbi("travelmate/wifi_add", {hideresetbtn=true, hidesavebtn=true})).leaf = true
entry({"admin", "services", "travelmate", "wifiedit"}, cbi("travelmate/wifi_edit", {hideresetbtn=true, hidesavebtn=true})).leaf = true
entry({"admin", "services", "travelmate", "wifidelete"}, cbi("travelmate/wifi_delete", {hideresetbtn=true, hidesavebtn=true})).leaf = true
end
function logread()
local logfile = util.trim(util.exec("logread -e 'travelmate'"))
template.render("travelmate/logread", {title = i18n.translate("Travelmate Logfile"), content = logfile})
templ.render("travelmate/logread", {title = i18n.translate("Travelmate Logfile"), content = logfile})
end

View file

@ -2,12 +2,13 @@
-- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs")
local uci = require("uci")
local uci = require("luci.model.uci").cursor()
local json = require("luci.jsonc")
local nw = require("luci.model.network").init()
local fw = require("luci.model.firewall").init()
local uplink = uci.get("network", "trm_wwan") or ""
local trmiface = uci.get("travelmate", "global", "trm_iface") or "trm_wwan"
local trminput = uci.get("travelmate", "global", "trm_rtfile") or "/tmp/trm_runtime.json"
local uplink = uci.get("network", trmiface) or ""
local parse = json.parse(fs.readfile(trminput) or "")
m = Map("travelmate", translate("Travelmate"),
@ -21,10 +22,56 @@ function m.on_after_commit(self)
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
end
-- Main travelmate options
s = m:section(NamedSection, "global", "travelmate")
-- Interface Wizard
if uplink == "" then
dv = s:option(DummyValue, "nil", translate("Interface Wizard"))
dv.template = "cbi/nullsection"
o = s:option(Value, "trm_iface", translate("Uplink interface"))
o.datatype = "and(uciname,rangelength(3,15))"
o.default = "trm_wwan"
o.rmempty = false
function o.validate(self, value)
iface = value
return iface
end
function o.write(self, section, value)
uci:set("travelmate", section, "trm_iface", iface)
uci:save("travelmate")
uci:commit("travelmate")
end
btn = s:option(Button, "", translate("Create Uplink Interface"),
translate("Create a new wireless wan uplink interface, configure it to use dhcp and ")
.. translate("add it to the wan zone of the firewall. This step has only to be done once."))
btn.inputtitle = translate("Add Interface")
btn.inputstyle = "apply"
btn.disabled = false
function btn.write()
local net = nw:add_network(iface, { proto = "dhcp" })
if net then
nw:save("network")
nw:commit("network")
local zone = fw:get_zone_by_network("wan")
if zone then
zone:add_network(iface)
fw:save("firewall")
fw:commit("firewall")
luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>&1")
end
end
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
end
return m
end
-- Main travelmate options
o1 = s:option(Flag, "trm_enabled", translate("Enable travelmate"))
o1.default = o1.disabled
o1.rmempty = false
@ -34,10 +81,11 @@ o2 = s:option(Flag, "trm_automatic", translate("Enable 'automatic' mode"),
o2.default = o2.enabled
o2.rmempty = false
o3 = s:option(Value, "trm_iface", translate("Restrict interface trigger to certain interface(s)"),
translate("Space separated list of interfaces that trigger travelmate processing. "..
"To disable event driven (re-)starts remove all entries."))
o3.rmempty = true
o3 = s:option(Value, "trm_iface", translate("Uplink / Trigger interface"),
translate("Name of the uplink interface that triggers travelmate processing."))
o3.datatype = "and(uciname,rangelength(3,15))"
o3.default = "trm_wwan"
o3.rmempty = false
o4 = s:option(Value, "trm_triggerdelay", translate("Trigger delay"),
translate("Additional trigger delay in seconds before travelmate processing begins."))
@ -49,42 +97,6 @@ o5 = s:option(Flag, "trm_debug", translate("Enable verbose debug logging"))
o5.default = o5.disabled
o5.rmempty = false
-- Interface setup
if uplink == "" then
dv = s:option(DummyValue, "_dummy", translate("Interface Setup"))
dv.template = "cbi/nullsection"
btn = s:option(Button, "", translate("Create Uplink Interface"),
translate("Automatically create a new wireless wan uplink interface 'trm_wwan', configure it to use dhcp and ")
.. translate("add it to the wan zone of the firewall. This step has only to be done once."))
btn.inputtitle = translate("Add Interface")
btn.inputstyle = "apply"
btn.disabled = false
function btn.write()
local name = "trm_wwan"
local net = nw:add_network(name, { proto = "dhcp" })
if net then
nw:save("network")
nw:commit("network")
local zone = fw:get_zone_by_network("wan")
if zone then
zone:add_network(name)
fw:save("firewall")
fw:commit("firewall")
end
luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>&1")
luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
end
end
else
dv = s:option(DummyValue, "_dummy", translate("Interface Setup"),
translate("<br />&nbsp;Network Interface 'trm_wwan' created successfully. ")
.. translatef("Scan &amp; Add new wireless stations via standard "
.. "<a href=\"%s\">"
.. "Wireless Setup</a>", luci.dispatcher.build_url("admin/network/wireless")))
dv.template = "cbi/nullsection"
end
-- Runtime information
ds = s:option(DummyValue, "_dummy", translate("Runtime information"))

View file

@ -0,0 +1,65 @@
-- Copyright 2017 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs")
local uci = require("luci.model.uci").cursor()
local http = require("luci.http")
local trmiface = uci.get("travelmate", "global", "trm_iface") or "trm_wwan"
m = SimpleForm("add", translate("Add Wireless Uplink Configuration"))
m.cancel = translate("Back to overview")
m.reset = false
function m.on_cancel()
http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))
end
m.hidden = {
device = http.formvalue("device"),
ssid = http.formvalue("ssid"),
wep = http.formvalue("wep"),
wpa_suites = http.formvalue("wpa_suites"),
wpa_version = http.formvalue("wpa_version")
}
wssid = m:field(Value, "ssid", translate("SSID"))
wssid.default = m.hidden.ssid
if (tonumber(m.hidden.wep) or 0) == 1 then
wkey = m:field(Value, "key", translate("WEP passphrase"),
translate("Specify the secret encryption key here."))
wkey.password = true
wkey.datatype = "wepkey"
elseif (tonumber(m.hidden.wpa_version) or 0) > 0 and
(m.hidden.wpa_suites == "PSK" or m.hidden.wpa_suites == "PSK2")
then
wkey = m:field(Value, "key", translate("WPA passphrase"),
translate("Specify the secret encryption key here."))
wkey.password = true
wkey.datatype = "wpakey"
end
function wssid.write(self, section, value)
newsection = uci:section("wireless", "wifi-iface", nil, {
mode = "sta",
network = trmiface,
device = m.hidden.device,
ssid = wssid:formvalue(section),
disabled = "1"
})
if (tonumber(m.hidden.wep) or 0) == 1 then
uci:set("wireless", newsection, "encryption", "wep-open")
uci:set("wireless", newsection, "key", "1")
uci:set("wireless", newsection, "key1", wkey:formvalue(section))
elseif (tonumber(m.hidden.wpa_version) or 0) > 0 then
uci:set("wireless", newsection, "encryption", "psk2")
uci:set("wireless", newsection, "key", wkey:formvalue(section))
else
uci:set("wireless", newsection, "encryption", "none")
end
uci:save("wireless")
uci:commit("wireless")
http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))
end
return m

View file

@ -0,0 +1,14 @@
-- Copyright 2017 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
local uci = require("luci.model.uci").cursor()
local http = require("luci.http")
local cfg = http.formvalue("cfg")
if cfg ~= nil then
uci:delete("wireless", cfg)
uci:save("wireless")
uci:commit("wireless")
end
http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))

View file

@ -0,0 +1,49 @@
-- Copyright 2017 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs")
local uci = require("luci.model.uci").cursor()
local http = require("luci.http")
m = SimpleForm("edit", translate("Edit Wireless Uplink Configuration"))
m.cancel = translate("Back to overview")
m.reset = false
function m.on_cancel()
http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))
end
m.hidden = {
cfg = http.formvalue("cfg")
}
local s = uci:get_all("wireless", m.hidden.cfg)
if s ~= nil then
wssid = m:field(Value, "ssid", translate("SSID"))
wssid.default = s.ssid
if s.encryption and s.key then
wkey = m:field(Value, "key", translatef("Passphrase (%s)", s.encryption))
wkey.password = true
wkey.default = s.key
if s.encryption == "wep" then
wkey.datatype = "wepkey"
else
wkey.datatype = "wpakey"
end
end
else
http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))
end
function wssid.write(self, section, value)
uci:set("wireless", m.hidden.cfg, "ssid", wssid:formvalue(section))
if s.encryption and s.key then
uci:set("wireless", m.hidden.cfg, "key", wkey:formvalue(section))
end
uci:save("wireless")
uci:commit("wireless")
http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))
end
return m

View file

@ -5,6 +5,6 @@ This is free software, licensed under the Apache License, Version 2.0
<%+cbi/valueheader%>
<input name="runtime" id="runtime" type="text" class="cbi-input-text" style="border: none; box-shadow: none; background-color: #ffffff; color: #0069d6;" value="<%=self:cfgvalue(section)%>" disabled="disabled" />
<input name="runtime" id="runtime" type="text" class="cbi-input-text" style="border:none; box-shadow:none; background-color:#ffffff; color:#0069d6;" value="<%=self:cfgvalue(section)%>" disabled="disabled" />
<%+cbi/valuefooter%>

View file

@ -0,0 +1,73 @@
<%#
Copyright 2017 Dirk Brenken (dev@brenken.org)
This is free software, licensed under the Apache License, Version 2.0
-%>
<%-
local write = io.write
local uci = require "luci.model.uci".cursor()
local trmiface = uci:get("travelmate", "global", "trm_iface") or "trm_wwan"
-%>
<%+header%>
<div class="cbi-map">
<h2 name="content"><%:Wireless Stations%></h2>
<div class="cbi-map-descr"><%:Provides an overview of all configured uplink interfaces for travelmate. You can edit and delete existing interfaces or scan for new uplinks.%></div>
<fieldset class="cbi-section">
<table class="cbi-section-table" style="empty-cells:hide">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell" style="text-align:left"><%:Device%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Mode%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Uplink Interface%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:SSID%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Encryption%></th>
<th class="cbi-section-table-cell" style="text-align:left" colspan="2"><%:Disabled%></th>
</tr>
<%
uci:foreach("wireless", "wifi-iface", function(s)
local section = s['.name']
local device = s.device or ""
local mode = s.mode or ""
local iface = s.network or ""
local ssid = s.ssid or ""
local encryption = s.encryption or ""
local disabled = s.disabled or ""
if iface == trmiface then
%>
<tr class="cbi-section-table-row cbi-rowstyle-6">
<td style="text-align:left"><%=device%></td>
<td style="text-align:left"><%=mode%></td>
<td style="text-align:left"><%=iface%></td>
<td style="text-align:left"><%=ssid%></td>
<td style="text-align:left"><%=encryption%></td>
<td style="text-align:left"><%=disabled%></td>
<td class="cbi-value-field" style="width:200px;text-align:right">
<input type="button" class="cbi-button cbi-button-edit" style="width:85px" onclick="location.href='<%=url('admin/services/travelmate/wifiedit')%>?cfg=<%=section%>'" title="<%:Edit this Uplink%>" value="<%:Edit%>" />
<input type="button" class="cbi-button cbi-button-remove" style="width:85px" onclick="location.href='<%=url('admin/services/travelmate/wifidelete')%>?cfg=<%=section%>'" title="<%:Delete this Uplink%>" value="<%:Delete%>"/>
</td>
</tr>
<%
end
end)
%>
</table>
</fieldset>
<div class="cbi-page-actions right">
<%
uci:foreach("wireless", "wifi-device", function(s)
local device = s[".name"]
%>
<form class="inline" action="<%=url('admin/services/travelmate/wifiscan')%>" method="post">
<input type="hidden" name="device" value="<%=device%>" />
<input type="hidden" name="token" value="<%=token%>" />
<input type="submit" class="cbi-button cbi-button-find" style="width:110px" title="<%:Find and join network on %><%=device%>" value="<%:Scan %><%=device%>" />
</form>
<%
end)
%>
</div>
<%+footer%>

View file

@ -0,0 +1,108 @@
<%#
Copyright 2017 Dirk Brenken (dev@brenken.org)
This is free software, licensed under the Apache License, Version 2.0
-%>
<%-
local sys = require "luci.sys"
local utl = require "luci.util"
local dev = luci.http.formvalue("device")
local iw = luci.sys.wifi.getiwinfo(dev)
if not iw then
luci.http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))
end
function format_wifi_encryption(info)
if info.wep == true then
return translate("WEP")
elseif info.wpa > 0 then
return translate("WPA / WPA2")
elseif info.enabled then
return translate("Unknown")
else
return translate("Open")
end
end
function percent_wifi_signal(info)
local qc = info.quality or 0
local qm = info.quality_max or 0
if info.bssid and qc > 0 and qm > 0 then
return math.floor((100 / qm) * qc)
else
return 0
end
end
function scanlist(times)
local i, k, v
local l = { }
local s = { }
for i = 1, times do
for k, v in ipairs(iw.scanlist or { }) do
if not s[v.bssid] then
l[#l+1] = v
s[v.bssid] = true
end
end
end
return l
end
-%>
<%+header%>
<div class="cbi-map">
<h2 name="content"><%:Wireless Scan%></h2>
<fieldset class="cbi-section">
<table class="cbi-section-table" style="empty-cells:hide">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell" style="text-align:left"><%:Uplink SSID%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Encryption%></th>
<th class="cbi-section-table-cell" style="text-align:left" colspan="2"><%:Signal strength%></th>
</tr>
<% for i, net in ipairs(scanlist(3)) do net.encryption = net.encryption or { } %>
<tr class="cbi-section-table-row cbi-rowstyle-4">
<td class="cbi-value-field" style="text-align:left">
<strong><%=net.ssid and utl.pcdata(net.ssid) or "<em>%s</em>" % translate("hidden")%></strong>
</td>
<td class="cbi-value-field" style="text-align:left">
<%=format_wifi_encryption(net.encryption)%>
</td>
<td class="cbi-value-field" style="text-align:left">
<%=percent_wifi_signal(net)%> %
</td>
<td class="cbi-value-field" style="width:120px; text-align:right">
<form class="inline" action="<%=url('admin/services/travelmate/wifiadd')%>" method="post">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
<input type="hidden" name="ssid" value="<%=utl.pcdata(net.ssid)%>" />
<input type="hidden" name="wep" value="<%=net.encryption.wep and 1 or 0%>" />
<% if net.encryption.wpa then %>
<input type="hidden" name="wpa_version" value="<%=net.encryption.wpa%>" />
<% for _, v in ipairs(net.encryption.auth_suites) do %><input type="hidden" name="wpa_suites" value="<%=v%>" />
<% end; for _, v in ipairs(net.encryption.group_ciphers) do %><input type="hidden" name="wpa_group" value="<%=v%>" />
<% end; for _, v in ipairs(net.encryption.pair_ciphers) do %><input type="hidden" name="wpa_pairwise" value="<%=v%>" />
<% end; end %>
<input class="cbi-button cbi-button-apply" style="width:110px" type="submit" value="<%:Add Uplink%>" />
</form>
</td>
</tr>
<% end %>
</table>
</fieldset>
<div class="cbi-page-actions right">
<form class="inline" action="<%=url('admin/services/travelmate/stations')%>" method="post">
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Back to overview%>" />
</form>
<form class="inline" action="<%=url('admin/services/travelmate/wifiscan')%>" method="post">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
<input class="cbi-button cbi-input-find" type="submit" value="<%:Repeat scan%>" />
</form>
</div>
<%+footer%>