4 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
20 local pairs, type, i18n, uci, math = pairs, type, luci.i18n, luci.model.uci, math
22 local iwi = require "iwinfo"
23 local utl = require "luci.util"
24 local uct = require "luci.model.uci.bind"
26 module "luci.model.wireless"
28 local ub = uct.bind("wireless")
32 cursor:unload("wireless")
33 cursor:load("wireless")
36 st = uci.cursor_state()
41 ub.uci:foreach("wireless", "wifi-iface",
45 local id = "%s.network%d" %{ s.device, count }
53 local dev = st:get("wireless", s['.name'], "ifname")
54 or st:get("wireless", s['.name'], "device")
56 local wtype = dev and iwi.type(dev)
59 ifs[id].winfo = iwi[wtype]
65 function get_device(self, dev)
69 function get_devices(self)
71 ub.uci:foreach("wireless", "wifi-device",
72 function(s) devs[#devs+1] = device(s['.name']) end)
76 function get_network(self, id)
78 return network(ifs[id].sid)
81 for n, _ in pairs(ifs) do
82 if ifs[n].sid == id then
89 function add_network(self, options)
90 if type(options) == "table" and options.device and
91 ub.uci:get("wireless", options.device) == "wifi-device"
93 local s = ub.uci:section("wireless", "wifi-iface", nil, options)
95 ub.uci:foreach("wireless", "wifi-iface", function(s) c = c + 1 end)
97 local id = "%s.network%d" %{ options.device, c }
104 local wtype = iwi.type(options.device)
106 ifs[id].winfo = iwi[wtype]
107 ifs[id].wdev = options.device
114 function del_network(self, id)
116 ub.uci:delete("wireless", ifs[id].sid)
120 for n, _ in pairs(ifs) do
121 if ifs[n].sid == id then
122 ub.uci:delete("wireless", id)
129 function shortname(self, iface)
130 if iface.wdev and iface.winfo then
132 i18n.translate(iface:active_mode()),
133 iface:active_ssid() or i18n.translate("(hidden)")
140 function get_i18n(self, iface)
141 if iface.wdev and iface.winfo then
142 return "%s: %s %q (%s)" %{
143 i18n.translate("Wireless Network"),
144 i18n.translate(iface:active_mode()),
145 iface:active_ssid() or i18n.translate("(hidden)"), iface.wdev
148 return "%s: %q" %{ i18n.translate("Wireless Network"), iface:name() }
152 function find_interfaces(self, iflist, brlist)
154 for iface, _ in pairs(ifs) do
155 iflist[iface] = ifs[iface]
159 function ignore_interface(self, iface)
160 if ifs and ifs[iface] then
163 return iwi.type(iface) and true or false
167 function add_interface(self, net, iface)
168 if ifs and ifs[iface] and ifs[iface].sid then
169 ub.uci:set("wireless", ifs[iface].sid, "network", net:name())
170 ifs[iface].network = net:name()
177 function del_interface(self, net, iface)
178 if ifs and ifs[iface] and ifs[iface].sid then
179 ub.uci:delete("wireless", ifs[iface].sid, "network")
187 device = ub:section("wifi-device")
188 device:property("type")
189 device:property("channel")
190 device:property_bool("disabled")
192 function device.name(self)
196 function device.is_up(self)
199 if not self:disabled() then
200 st:foreach("wireless", "wifi-iface",
202 if s.device == self:name() and s.up == "1" then
212 function device.get_networks(self)
215 ub.uci:foreach("wireless", "wifi-iface",
217 if s.device == self:name() then
218 nets[#nets+1] = network(s['.name'])
226 network = ub:section("wifi-iface")
227 network:property("mode")
228 network:property("ssid")
229 network:property("bssid")
230 network:property("network")
232 function network._init(self, sid)
235 ub.uci:foreach("wireless", "wifi-iface",
238 return s['.name'] ~= sid
241 local parent_dev = st:get("wireless", sid, "device")
242 or ub.uci:get("wireless", sid, "device")
244 local dev = st:get("wireless", sid, "ifname")
248 self.id = "%s.network%d" %{ parent_dev, count }
250 local wtype = iwi.type(dev)
251 if dev and wtype then
252 self.winfo = iwi[wtype]
258 function network.name(self)
262 function network.ifname(self)
266 function network.get_device(self)
268 return device(self.device)
272 function network.is_up(self)
273 return (st:get("wireless", self.sid, "up") == "1")
276 function network.active_mode(self)
277 local m = self.winfo and self.winfo.mode(self.wdev)
280 if m == "ap" then m = "AP"
281 elseif m == "sta" then m = "Client"
282 elseif m == "adhoc" then m = "Ad-Hoc"
283 elseif m == "mesh" then m = "Mesh"
284 elseif m == "monitor" then m = "Monitor"
290 function network.active_mode_i18n(self)
291 return i18n.translate(self:active_mode())
294 function network.active_ssid(self)
295 return self.winfo and self.winfo.ssid(self.wdev) or
299 function network.active_bssid(self)
300 return self.winfo and self.winfo.bssid(self.wdev) or
301 self:bssid() or "00:00:00:00:00:00"
304 function network.active_encryption(self)
305 return self.winfo and self.winfo.enctype(self.wdev) or "-"
308 function network.assoclist(self)
309 return self.winfo and self.winfo.assoclist(self.wdev) or { }
312 function network.frequency(self)
313 local freq = self.winfo and self.winfo.frequency(self.wdev)
314 return freq and freq > 0 and "%.03f" % (freq / 1000)
317 function network.bitrate(self)
318 local rate = self.winfo and self.winfo.bitrate(self.wdev)
319 return rate and rate > 0 and (rate / 1000)
322 function network.channel(self)
323 return self.winfo and self.winfo.channel(self.wdev)
326 function network.signal(self)
327 return self.winfo and self.winfo.signal(self.wdev) or 0
330 function network.noise(self)
331 return self.winfo and self.winfo.noise(self.wdev) or 0
334 function network.signal_level(self, s, n)
335 if self:active_bssid() ~= "00:00:00:00:00:00" then
336 local signal = s or self:signal()
337 local noise = n or self:noise()
339 if signal < 0 and noise < 0 then
340 local snr = -1 * (noise - signal)
341 return math.floor(snr / 5)
350 function network.signal_percent(self)
351 local qc = self.winfo and
352 self.winfo.quality(self.wdev) or 0
354 local qm = self.winfo and
355 self.winfo.quality_max(self.wdev) or 0
357 if qc > 0 and qm > 0 then
358 return math.floor((100 / qm) * qc)