libs/core: Fix wireless network ids
[project/luci.git] / libs / core / luasrc / model / wireless.lua
index bbe7640..3d4b2b0 100644 (file)
@@ -17,7 +17,7 @@ limitations under the License.
 
 ]]--
 
-local pairs, i18n, uci, math = pairs, luci.i18n, luci.model.uci, math
+local pairs, type, i18n, uci, math = pairs, type, luci.i18n, luci.model.uci, math
 
 local iwi = require "iwinfo"
 local utl = require "luci.util"
@@ -66,6 +66,13 @@ function get_device(self, dev)
        return device(dev)
 end
 
+function get_devices(self)
+       local devs = { }
+       ub.uci:foreach("wireless", "wifi-device",
+               function(s) devs[#devs+1] = device(s['.name']) end)
+       return devs
+end
+
 function get_network(self, id)
        if ifs[id] then
                return network(ifs[id].sid)
@@ -79,11 +86,51 @@ function get_network(self, id)
        end
 end
 
+function add_network(self, options)
+       if type(options) == "table" and options.device and
+               ub.uci:get("wireless", options.device) == "wifi-device"
+       then
+               local s = ub.uci:section("wireless", "wifi-iface", nil, options)
+               local c = 1
+               ub.uci:foreach("wireless", "wifi-iface", function(s) c = c + 1 end)
+
+               local id = "%s.network%d" %{ options.device, c }
+               ifs[id] = {
+                       id    = id,
+                       sid   = s,
+                       count = c
+               }
+
+               local wtype = iwi.type(options.device)
+               if wtype then
+                       ifs[id].winfo = iwi[wtype]
+                       ifs[id].wdev  = options.device
+               end
+
+               return network(s)
+       end
+end
+
+function del_network(self, id)
+       if ifs[id] then
+               ub.uci:delete("wireless", ifs[id].sid)
+               ifs[id] = nil
+       else
+               local n
+               for n, _ in pairs(ifs) do
+                       if ifs[n].sid == id then
+                               ub.uci:delete("wireless", id)
+                               ifs[n] = nil
+                       end
+               end
+       end
+end
+
 function shortname(self, iface)
        if iface.wdev and iface.winfo then
                return "%s %q" %{
-                       i18n.translate("a_s_if_iwmode_" .. iface:active_mode(), iface.winfo.mode(iface.wdev)), 
-                       iface:active_ssid() or "(hidden)"
+                       i18n.translate(iface:active_mode()), 
+                       iface:active_ssid() or i18n.translate("(hidden)")
                }
        else
                return iface:name()
@@ -93,39 +140,15 @@ end
 function get_i18n(self, iface)
        if iface.wdev and iface.winfo then
                return "%s: %s %q (%s)" %{
-                       i18n.translate("a_s_if_wifinet", "Wireless Network"),
-                       i18n.translate("a_s_if_iwmode_" .. iface:active_mode(), iface.winfo.mode(iface.wdev)),
-                       iface:active_ssid() or "(hidden)", iface.wdev
+                       i18n.translate("Wireless Network"),
+                       i18n.translate(iface:active_mode()),
+                       iface:active_ssid() or i18n.translate("(hidden)"), iface.wdev
                }
        else
-               return "%s: %q" %{ i18n.translate("a_s_if_wifinet", "Wireless Network"), iface:name() }
+               return "%s: %q" %{ i18n.translate("Wireless Network"), iface:name() }
        end
 end
 
-function rename_network(self, old, new)
-       local i
-       for i, _ in pairs(ifs) do
-               if ifs[i].network == old then
-                       ifs[i].network = new
-               end
-       end
-
-       ub.uci:foreach("wireless", "wifi-iface",
-               function(s)
-                       if s.network == old then
-                               if new then 
-                                       ub.uci:set("wireless", s['.name'], "network", new)
-                               else
-                                       ub.uci:delete("wireless", s['.name'], "network")
-                               end
-                       end
-               end)
-end
-
-function del_network(self, old)
-       return self:rename_network(old, nil)
-end
-
 function find_interfaces(self, iflist, brlist)
        local iface
        for iface, _ in pairs(ifs) do
@@ -164,12 +187,28 @@ end
 device = ub:section("wifi-device")
 device:property("type")
 device:property("channel")
-device:property("disabled")
+device:property_bool("disabled")
 
 function device.name(self)
        return self.sid
 end
 
+function device.is_up(self)
+       local rv = false
+
+       if not self:disabled() then
+               st:foreach("wireless", "wifi-iface",
+                       function(s)
+                               if s.device == self:name() and s.up == "1" then
+                                       rv = true
+                                       return false
+                               end
+                       end)
+       end
+
+       return rv
+end
+
 function device.get_networks(self)
        local nets = { }
 
@@ -193,23 +232,26 @@ network:property("network")
 function network._init(self, sid)
        local count = 0
 
-       ub.uci:foreach("wireless", "wifi-iface",
-               function(s)
-                       count = count + 1
-                       return s['.name'] ~= sid
-               end)
-       
+       local parent_dev = st:get("wireless", sid, "device")
+               or ub.uci:get("wireless", sid, "device")
+
        local dev = st:get("wireless", sid, "ifname")
-               or st:get("wireless", sid, "device")
+               or parent_dev
 
        if dev then
-               self.id = "%s.network%d" %{ dev, count }
-
-               local wtype = iwi.type(dev)
-               if dev and wtype then
-                       self.winfo = iwi[wtype]
-                       self.wdev  = dev
-               end
+               ub.uci:foreach("wireless", "wifi-iface",
+                       function(s)
+                               count = count + 1
+                               if s['.name'] == sid then
+                                       self.id = "%s.network%d" %{ parent_dev, count }
+
+                                       local wtype = iwi.type(dev)
+                                       if dev and wtype then
+                                               self.winfo = iwi[wtype]
+                                               self.wdev  = dev
+                                       end
+                               end
+                       end)
        end
 end
 
@@ -227,24 +269,26 @@ function network.get_device(self)
        end
 end
 
+function network.is_up(self)
+       return (st:get("wireless", self.sid, "up") == "1")
+end
+
 function network.active_mode(self)
        local m = self.winfo and self.winfo.mode(self.wdev)
-       if m == "Master" or m == "Auto" then
-               m = "ap"
-       elseif m == "Ad-Hoc" then
-               m = "adhoc"
-       elseif m == "Client" then
-               m = "sta"
-       elseif m then
-               m = m:lower()
-       else
+       if not m then
                m = self:mode()
+               if     m == "ap"      then m = "AP"
+               elseif m == "sta"     then m = "Client"
+               elseif m == "adhoc"   then m = "Ad-Hoc"
+               elseif m == "mesh"    then m = "Mesh"
+               elseif m == "monitor" then m = "Monitor"
+               end
        end
-       return m or "ap"
+       return m or "Client"
 end
 
 function network.active_mode_i18n(self)
-       return i18n.translate("a_s_if_iwmode_" .. self:active_mode())
+       return i18n.translate(self:active_mode())
 end
 
 function network.active_ssid(self)
@@ -257,6 +301,28 @@ function network.active_bssid(self)
                self:bssid() or "00:00:00:00:00:00"
 end
 
+function network.active_encryption(self)
+       return self.winfo and self.winfo.enctype(self.wdev) or "-"
+end
+
+function network.assoclist(self)
+       return self.winfo and self.winfo.assoclist(self.wdev) or { }
+end
+
+function network.frequency(self)
+       local freq = self.winfo and self.winfo.frequency(self.wdev)
+       return freq and freq > 0 and "%.03f" % (freq / 1000)
+end
+
+function network.bitrate(self)
+       local rate = self.winfo and self.winfo.bitrate(self.wdev)
+       return rate and rate > 0 and (rate / 1000)
+end
+
+function network.channel(self)
+       return self.winfo and self.winfo.channel(self.wdev)
+end
+
 function network.signal(self)
        return self.winfo and self.winfo.signal(self.wdev) or 0
 end
@@ -265,12 +331,12 @@ function network.noise(self)
        return self.winfo and self.winfo.noise(self.wdev) or 0
 end
 
-function network.signal_level(self)
+function network.signal_level(self, s, n)
        if self:active_bssid() ~= "00:00:00:00:00:00" then
-               local signal = self:signal()
-               local noise  = self:noise()
+               local signal = s or self:signal()
+               local noise  = n or self:noise()
 
-               if signal > 0 and noise > 0 then
+               if signal < 0 and noise < 0 then
                        local snr = -1 * (noise - signal)
                        return math.floor(snr / 5)
                else