61dba245d5315db0f79e67991a059466653cef79
[project/luci.git] / libs / core / luasrc / model / wireless.lua
1 --[[
2 LuCI - Wireless model
3
4 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
5
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
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
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.
17
18 ]]--
19
20 local pairs, i18n, uci, math = pairs, luci.i18n, luci.model.uci, math
21
22 local iwi = require "iwinfo"
23 local utl = require "luci.util"
24 local uct = require "luci.model.uci.bind"
25
26 module "luci.model.network.wireless"
27
28 local ub = uct.bind("wireless")
29 local st, ifs
30
31 function init(self, cursor)
32         cursor:unload("wireless")
33         cursor:load("wireless")
34         ub:init(cursor)
35
36         st = uci.cursor_state()
37         ifs = { }
38
39         local count = 0
40
41         ub.uci:foreach("wireless", "wifi-iface",
42                 function(s)
43                         count = count + 1
44
45                         local id = "%s.network%d" %{ self.device, count }
46
47                         ifs[id] = {
48                                 id    = id,
49                                 sid   = s['.name'],
50                                 count = count
51                         }
52
53                         local dev = st:get("wireless", s['.name'], "ifname")
54                                 or st:get("wireless", s['.name'], "device")
55
56                         local wtype = dev and iwi.type(dev)
57
58                         if dev and wtype then
59                                 ifs[id].winfo = iwi[wtype]
60                                 ifs[id].wdev  = dev
61                         end
62                 end)
63 end
64
65 function get_device(self, dev)
66         return device(dev)
67 end
68
69 function get_network(self, id)
70         if ifs[id] then
71                 return network(ifs[id].sid)
72         else
73                 local n
74                 for n, _ in pairs(ifs) do
75                         if ifs[n].sid == id then
76                                 return network(id)
77                         end
78                 end
79         end
80 end
81
82 function shortname(self, iface)
83         if iface.dev and iface.dev.wifi then
84                 return "%s %q" %{
85                         i18n.translate("a_s_if_iwmode_" .. (iface.dev.wifi.mode or "ap")), 
86                         iface.dev.wifi.ssid or iface.dev.wifi.bssid or "(hidden)"
87                 }
88         else
89                 return iface:name()
90         end
91 end
92
93 function get_i18n(self, iface)
94         if iface.dev and iface.dev.wifi then
95                 return "%s: %s %q" %{
96                         i18n.translate("a_s_if_wifinet", "Wireless Network"),
97                         i18n.translate("a_s_if_iwmode_" .. (iface.dev.wifi.mode or "ap"), iface.dev.wifi.mode or "AP"),
98                         iface.dev.wifi.ssid or iface.dev.wifi.bssid or "(hidden)"
99                 }
100         else
101                 return "%s: %q" %{ i18n.translate("a_s_if_wifinet", "Wireless Network"), iface:name() }
102         end
103 end
104
105 function rename_network(self, old, new)
106         local i
107         for i, _ in pairs(ifs) do
108                 if ifs[i].network == old then
109                         ifs[i].network = new
110                 end
111         end
112
113         ub.uci:foreach("wireless", "wifi-iface",
114                 function(s)
115                         if s.network == old then
116                                 if new then 
117                                         ub.uci:set("wireless", s['.name'], "network", new)
118                                 else
119                                         ub.uci:delete("wireless", s['.name'], "network")
120                                 end
121                         end
122                 end)
123 end
124
125 function del_network(self, old)
126         return self:rename_network(old, nil)
127 end
128
129 function find_interfaces(self, iflist, brlist)
130         local iface
131         for iface, _ in pairs(ifs) do
132                 iflist[iface] = ifs[iface]
133         end
134 end
135
136 function ignore_interface(self, iface)
137         if ifs and ifs[iface] then
138                 return false
139         else
140                 return iwi.type(iface) and true or false
141         end
142 end
143
144 function add_interface(self, net, iface)
145         if ifs and ifs[iface] and ifs[iface].sid then
146                 ub.uci:set("wireless", ifs[iface].sid, "network", net:name())
147                 ifs[iface].network = net:name()
148                 return true
149         end
150
151         return false
152 end
153
154 function del_interface(self, net, iface)
155         if ifs and ifs[iface] and ifs[iface].sid then
156                 ub.uci:delete("wireless", ifs[iface].sid, "network")
157                 --return true
158         end
159
160         return false
161 end
162
163
164 device = ub:section("wifi-device")
165 device:property("type")
166 device:property("channel")
167 device:property("disabled")
168
169 function device.name(self)
170         return self.sid
171 end
172
173 function device.get_networks(self)
174         local nets = { }
175
176         ub.uci:foreach("wireless", "wifi-iface",
177                 function(s)
178                         if s.device == self:name() then
179                                 nets[#nets+1] = network(s['.name'])
180                         end
181                 end)
182
183         return nets
184 end
185
186
187 network = ub:section("wifi-iface")
188 network:property("mode")
189 network:property("ssid")
190 network:property("bssid")
191 network:property("network")
192
193 function network._init(self, sid)
194         local count = 0
195
196         ub.uci:foreach("wireless", "wifi-iface",
197                 function(s)
198                         count = count + 1
199                         return s['.name'] ~= sid
200                 end)
201
202         self.id = "%s.network%d" %{ self.device, count }
203         
204         local dev = st:get("wireless", sid, "ifname")
205                 or st:get("wireless", sid, "device")
206
207         local wtype = dev and iwi.type(dev)
208
209         if dev and wtype then
210                 self.winfo = iwi[wtype]
211                 self.wdev  = dev
212         end
213 end
214
215 function network.name(self)
216         return self.id
217 end
218
219 function network.ifname(self)
220         return self.wdev
221 end
222
223 function network.get_device(self)
224         if self.device then
225                 return device(self.device)
226         end
227 end
228
229 function network.active_mode(self)
230         local m = self.winfo and self.winfo.mode(self.wdev)
231         if m == "Master" or m == "Auto" then
232                 m = "ap"
233         elseif m == "Ad-Hoc" then
234                 m = "adhoc"
235         elseif m == "Client" then
236                 m = "sta"
237         elseif m then
238                 m = m:lower()
239         else
240                 m = self:mode()
241         end
242         return m or "ap"
243 end
244
245 function network.active_mode_i18n(self)
246         return i18n.translate("a_s_if_iwmode_" .. self:active_mode())
247 end
248
249 function network.active_ssid(self)
250         return self.winfo and self.winfo.ssid(self.wdev) or
251                 self:ssid()
252 end
253
254 function network.active_bssid(self)
255         return self.winfo and self.winfo.bssid(self.wdev) or
256                 self:bssid() or "00:00:00:00:00:00"
257 end
258
259 function network.signal(self)
260         return self.winfo and self.winfo.signal(self.wdev) or 0
261 end
262
263 function network.noise(self)
264         return self.winfo and self.winfo.noise(self.wdev) or 0
265 end
266
267 function network.signal_level(self)
268         if self:active_bssid() ~= "00:00:00:00:00:00" then
269                 local signal = self:signal()
270                 local noise  = self:noise()
271
272                 if signal > 0 and noise > 0 then
273                         local snr = -1 * (noise - signal)
274                         return math.floor(snr / 5)
275                 else
276                         return 0
277                 end
278         else
279                 return -1
280         end
281 end
282
283 function network.signal_percent(self)
284         local qc = self.winfo and
285                 self.winfo.quality(self.wdev) or 0
286
287         local qm = self.winfo and
288                 self.winfo.quality_max(self.wdev) or 0
289
290         if qc > 0 and qm > 0 then
291                 return math.floor((100 / qm) * qc)
292         else
293                 return 0
294         end
295 end
296