libs/core: fixes luci.model.wireless
[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.wireless"
27
28 local ub = uct.bind("wireless")
29 local st, ifs
30
31 function init(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" %{ s.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.wdev and iface.winfo then
84 return "%s %q" %{
85 i18n.translate("a_s_if_iwmode_" .. iface:active_mode(), iface.winfo.mode(iface.wdev)),
86 iface:active_ssid() or "(hidden)"
87 }
88 else
89 return iface:name()
90 end
91 end
92
93 function get_i18n(self, iface)
94 if iface.wdev and iface.winfo then
95 return "%s: %s %q (%s)" %{
96 i18n.translate("a_s_if_wifinet", "Wireless Network"),
97 i18n.translate("a_s_if_iwmode_" .. iface:active_mode(), iface.winfo.mode(iface.wdev)),
98 iface:active_ssid() or "(hidden)", iface.wdev
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 local dev = st:get("wireless", sid, "ifname")
203 or st:get("wireless", sid, "device")
204
205 if dev then
206 self.id = "%s.network%d" %{ dev, count }
207
208 local wtype = iwi.type(dev)
209 if dev and wtype then
210 self.winfo = iwi[wtype]
211 self.wdev = dev
212 end
213 end
214 end
215
216 function network.name(self)
217 return self.id
218 end
219
220 function network.ifname(self)
221 return self.wdev
222 end
223
224 function network.get_device(self)
225 if self.device then
226 return device(self.device)
227 end
228 end
229
230 function network.active_mode(self)
231 local m = self.winfo and self.winfo.mode(self.wdev)
232 if m == "Master" or m == "Auto" then
233 m = "ap"
234 elseif m == "Ad-Hoc" then
235 m = "adhoc"
236 elseif m == "Client" then
237 m = "sta"
238 elseif m then
239 m = m:lower()
240 else
241 m = self:mode()
242 end
243 return m or "ap"
244 end
245
246 function network.active_mode_i18n(self)
247 return i18n.translate("a_s_if_iwmode_" .. self:active_mode())
248 end
249
250 function network.active_ssid(self)
251 return self.winfo and self.winfo.ssid(self.wdev) or
252 self:ssid()
253 end
254
255 function network.active_bssid(self)
256 return self.winfo and self.winfo.bssid(self.wdev) or
257 self:bssid() or "00:00:00:00:00:00"
258 end
259
260 function network.signal(self)
261 return self.winfo and self.winfo.signal(self.wdev) or 0
262 end
263
264 function network.noise(self)
265 return self.winfo and self.winfo.noise(self.wdev) or 0
266 end
267
268 function network.signal_level(self)
269 if self:active_bssid() ~= "00:00:00:00:00:00" then
270 local signal = self:signal()
271 local noise = self:noise()
272
273 if signal > 0 and noise > 0 then
274 local snr = -1 * (noise - signal)
275 return math.floor(snr / 5)
276 else
277 return 0
278 end
279 else
280 return -1
281 end
282 end
283
284 function network.signal_percent(self)
285 local qc = self.winfo and
286 self.winfo.quality(self.wdev) or 0
287
288 local qm = self.winfo and
289 self.winfo.quality_max(self.wdev) or 0
290
291 if qc > 0 and qm > 0 then
292 return math.floor((100 / qm) * qc)
293 else
294 return 0
295 end
296 end
297