Merge pull request #1933 from Ansuel/hostname_upnp
[oweals/luci.git] / modules / luci-mod-admin-full / luasrc / model / cbi / admin_network / wifi_overview.lua
1 -- Copyright 2018 Jo-Philipp Wich <jo@mein.io>
2 -- Licensed to the public under the Apache License 2.0.
3
4 local fs = require "nixio.fs"
5 local utl = require "luci.util"
6 local tpl = require "luci.template"
7 local ntm = require "luci.model.network"
8
9 local has_iwinfo = pcall(require, "iwinfo")
10
11 function guess_wifi_hw(dev)
12         local bands = ""
13         local ifname = dev:name()
14         local name, idx = ifname:match("^([a-z]+)(%d+)")
15         idx = tonumber(idx)
16
17         if has_iwinfo then
18                 local bl = dev.iwinfo.hwmodelist
19                 if bl and next(bl) then
20                         if bl.a then bands = bands .. "a" end
21                         if bl.b then bands = bands .. "b" end
22                         if bl.g then bands = bands .. "g" end
23                         if bl.n then bands = bands .. "n" end
24                         if bl.ac then bands = bands .. "ac" end
25                 end
26
27                 local hw = dev.iwinfo.hardware_name
28                 if hw then
29                         return "%s 802.11%s" %{ hw, bands }
30                 end
31         end
32
33         -- wl.o
34         if name == "wl" then
35                 local name = translatef("Broadcom 802.11%s Wireless Controller", bands)
36                 local nm   = 0
37
38                 local fd = nixio.open("/proc/bus/pci/devices", "r")
39                 if fd then
40                         local ln
41                         for ln in fd:linesource() do
42                                 if ln:match("wl$") then
43                                         if nm == idx then
44                                                 local version = ln:match("^%S+%s+%S%S%S%S([0-9a-f]+)")
45                                                 name = translatef(
46                                                         "Broadcom BCM%04x 802.11 Wireless Controller",
47                                                         tonumber(version, 16)
48                                                 )
49
50                                                 break
51                                         else
52                                                 nm = nm + 1
53                                         end
54                                 end
55                         end
56                         fd:close()
57                 end
58
59                 return name
60
61         -- dunno yet
62         else
63                 return translatef("Generic 802.11%s Wireless Controller", bands)
64         end
65 end
66
67 local tpl_radio = tpl.Template(nil, [[
68         <div class="cbi-section-node">
69                 <div class="table">
70                         <!-- physical device -->
71                         <div class="tr cbi-rowstyle-2">
72                                 <div class="td col-2 center middle">
73                                         <span class="ifacebadge"><img src="<%=resource%>/icons/wifi_toggled.png" id="<%=dev:name()%>-iw-upstate" /> <%=dev:name()%></span>
74                                 </div>
75                                 <div class="td col-7 left middle">
76                                         <big><strong><%=hw%></strong></big><br />
77                                         <span id="<%=dev:name()%>-iw-devinfo"></span>
78                                 </div>
79                                 <div class="td middle cbi-section-actions">
80                                         <div>
81                                                 <input type="button" class="cbi-button cbi-button-neutral" title="<%:Restart radio interface%>" value="<%:Restart%>" onclick="wifi_restart(event)" data-radio="<%=dev:name()%>" />
82
83                                                 <form action="<%=url('admin/network/wireless_join')%>" method="post" class="inline">
84                                                         <input type="hidden" name="device" value="<%=dev:name()%>" />
85                                                         <input type="hidden" name="token" value="<%=token%>" />
86                                                         <input type="submit" class="cbi-button cbi-button-action important" title="<%:Find and join network%>" value="<%:Scan%>" />
87                                                 </form>
88                                                 <form action="<%=url('admin/network/wireless_add')%>" method="post" class="inline">
89                                                         <input type="hidden" name="device" value="<%=dev:name()%>" />
90                                                         <input type="hidden" name="token" value="<%=token%>" />
91                                                         <input type="submit" class="cbi-button cbi-button-add" title="<%:Provide new network%>" value="<%:Add%>" />
92                                                 </form>
93                                         </div>
94                                 </div>
95                         </div>
96                         <!-- /physical device -->
97
98                         <!-- network list -->
99                         <% if #wnets > 0 then %>
100                                 <% for i, net in ipairs(wnets) do local disabled = (dev:get("disabled") == "1" or net:get("disabled") == "1") %>
101                                 <div class="tr cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
102                                         <div class="td col-2 center middle" id="<%=net:id()%>-iw-signal">
103                                                 <span class="ifacebadge" title="<%:Not associated%>"><img src="<%=resource%>/icons/signal-<%= disabled and "none" or "0" %>.png" /> 0%</span>
104                                         </div>
105                                         <div class="td col-7 left middle" id="<%=net:id()%>-iw-status" data-network="<%=net:id()%>" data-disabled="<%= disabled and "true" or "false" %>">
106                                                 <em><%= disabled and translate("Wireless is disabled") or translate("Collecting data...") %></em>
107                                         </div>
108                                         <div class="td middle cbi-section-actions">
109                                                 <div>
110                                                         <% if disabled then %>
111                                                                 <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="1" />
112                                                                 <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Enable this network%>" value="<%:Enable%>" onclick="this.previousElementSibling.value='0'" />
113                                                         <% else %>
114                                                                 <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="0" />
115                                                                 <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Disable this network%>" value="<%:Disable%>" onclick="this.previousElementSibling.value='1'" />
116                                                         <% end %>
117
118                                                         <input type="button" class="cbi-button cbi-button-action important" onclick="location.href='<%=net:adminlink()%>'" title="<%:Edit this network%>" value="<%:Edit%>" />
119
120                                                         <input name="cbid.wireless.<%=net:name()%>.__delete__" type="hidden" value="" />
121                                                         <input name="cbi.apply" type="submit" class="cbi-button cbi-button-negative" title="<%:Delete this network%>" value="<%:Remove%>" onclick="wifi_delete(event)" />
122                                                 </div>
123                                         </div>
124                                 </div>
125                                 <% end %>
126                         <% else %>
127                                 <div class="tr cbi-rowstyle-2">
128                                         <div class="td left">
129                                                 <em><%:No network configured on this device%></em>
130                                         </div>
131                                 </div>
132                         <% end %>
133                         <!-- /network list -->
134                 </div>
135         </div>
136 ]])
137
138
139 m = Map("wireless", translate("Wireless Overview"))
140 m:chain("network")
141 m.pageaction = false
142
143 if not has_iwinfo then
144         s = m:section(NamedSection, "__warning__")
145
146         function s.render(self)
147                 tpl.render_string([[
148                         <div class="alert-message warning">
149                                 <h4><%:Package libiwinfo required!%></h4>
150                                 <p><%_The <em>libiwinfo-lua</em> package is not installed. You must install this component for working wireless configuration!%></p>
151                         </div>
152                 ]])
153         end
154 end
155
156 local _, dev, net
157 for _, dev in ipairs(ntm:get_wifidevs()) do
158         s = m:section(TypedSection)
159         s.wnets = dev:get_wifinets()
160
161         function s.render(self, sid)
162                 tpl_radio:render({
163                         hw = guess_wifi_hw(dev),
164                         dev = dev,
165                         wnets = self.wnets
166                 })
167         end
168
169         function s.cfgsections(self)
170                 local _, net, sl = nil, nil, { }
171                 for _, net in ipairs(self.wnets) do
172                         sl[#sl+1] = net:name()
173                         self.wnets[net:name()] = net
174                 end
175                 return sl
176         end
177
178         o = s:option(Value, "__disable__")
179
180         function o.cfgvalue(self, sid)
181                 local wnet = self.section.wnets[sid]
182                 local wdev = wnet:get_device()
183
184                 return ((wnet and wnet:get("disabled") == "1") or
185                             (wdev and wdev:get("disabled") == "1")) and "1" or "0"
186         end
187
188         function o.write(self, sid, value)
189                 local wnet = self.section.wnets[sid]
190                 local wdev = wnet:get_device()
191
192                 if value ~= "1" then
193                         wnet:set("disabled", nil)
194                         wdev:set("disabled", nil)
195                 else
196                         wnet:set("disabled", "1")
197                 end
198         end
199
200         o.remove = o.write
201
202
203         o = s:option(Value, "__delete__")
204
205         function o.write(self, sid, value)
206                 local wnet = self.section.wnets[sid]
207                 local nets = wnet:get_networks()
208
209                 ntm:del_wifinet(wnet:id())
210
211                 local _, net
212                 for _, net in ipairs(nets) do
213                         if net:is_empty() then
214                                 ntm:del_network(net:name())
215                         end
216                 end
217         end
218 end
219
220 s = m:section(NamedSection, "__script__")
221 s.template = "admin_network/wifi_overview_status"
222
223 s = m:section(NamedSection, "__assoclist__")
224
225 function s.render(self, sid)
226         tpl.render_string([[
227                 <h2><%:Associated Stations%></h2>
228                 <%+admin_network/wifi_assoclist%>
229         ]])
230 end
231
232 return m