1d0175ff1e8dfa7c4bc6be542e4b1ebd2fcb3f5b
[project/luci.git] / modules / freifunk / luasrc / controller / freifunk / freifunk.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.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 $Id$
13 ]]--
14
15 module("luci.controller.freifunk.freifunk", package.seeall)
16
17 function index()
18         local uci = require "luci.model.uci".cursor()
19         local page
20
21         -- Frontend
22         page          = node()
23         page.lock     = true
24         page.target   = alias("freifunk")
25         page.subindex = true
26         page.index    = false
27
28         page          = node("freifunk")
29         page.title    = _("Freifunk")
30         page.target   = alias("freifunk", "index")
31         page.order    = 5
32         page.setuser  = "nobody"
33         page.setgroup = "nogroup"
34         page.i18n     = "freifunk"
35         page.index    = true
36
37         page          = node("freifunk", "index")
38         page.target   = template("freifunk/index")
39         page.title    = _("Overview")
40         page.order    = 10
41         page.indexignore = true
42
43         page          = node("freifunk", "contact")
44         page.target   = template("freifunk/contact")
45         page.title    = _("Contact")
46         page.order    = 15
47
48         page          = node("freifunk", "status")
49         page.target   = template("freifunk/public_status")
50         page.title    = _("Status")
51         page.order    = 20
52         page.i18n     = "base"
53         page.setuser  = false
54         page.setgroup = false
55
56         entry({"freifunk", "status.json"}, call("jsonstatus"))
57         entry({"freifunk", "status", "zeroes"}, call("zeroes"), "Testdownload")
58         entry({"freifunk", "status", "public_status_json"}, call("public_status_json")).leaf = true
59
60         assign({"freifunk", "olsr"}, {"admin", "status", "olsr"}, _("OLSR"), 30)
61
62         if nixio.fs.access("/etc/config/luci_statistics") then
63                 assign({"freifunk", "graph"}, {"admin", "statistics", "graph"}, _("Statistics"), 40)
64         end
65
66         -- backend
67         assign({"mini", "freifunk"}, {"admin", "freifunk"}, _("Freifunk"), 5)
68         entry({"admin", "freifunk"}, alias("admin", "freifunk", "index"), _("Freifunk"), 5)
69
70         page        = node("admin", "freifunk")
71         page.target = template("freifunk/adminindex")
72         page.title  = _("Freifunk")
73         page.order  = 5
74
75         page        = node("admin", "freifunk", "basics")
76         page.target = cbi("freifunk/basics")
77         page.title  = _("Basic Settings")
78         page.order  = 5
79         
80         page        = node("admin", "freifunk", "basics", "profile")
81         page.target = cbi("freifunk/profile")
82         page.title  = _("Profile")
83         page.order  = 10
84
85         page        = node("admin", "freifunk", "basics", "profile_expert")
86         page.target = cbi("freifunk/profile_expert")
87         page.title  = _("Profile (Expert)")
88         page.order  = 20
89
90         page        = node("admin", "freifunk", "Index-Page")
91         page.target = cbi("freifunk/user_index")
92         page.title  = _("Index Page")
93         page.order  = 50
94
95         page        = node("admin", "freifunk", "contact")
96         page.target = cbi("freifunk/contact")
97         page.title  = _("Contact")
98         page.order  = 15
99
100         entry({"freifunk", "map"}, template("freifunk-map/frame"), _("Map"), 50)
101         entry({"freifunk", "map", "content"}, template("freifunk-map/map"), nil, 51)
102         entry({"admin", "freifunk", "profile_error"}, template("freifunk/profile_error"))
103 end
104
105 local function fetch_olsrd()
106         local sys = require "luci.sys"
107         local util = require "luci.util"
108         local table = require "table"
109         local rawdata = sys.httpget("http://127.0.0.1:2006/")
110
111         if #rawdata == 0 then
112                 if nixio.fs.access("/proc/net/ipv6_route", "r") then
113                         rawdata = sys.httpget("http://[::1]:2006/")
114                         if #rawdata == 0 then
115                                 return nil
116                         end
117                 else
118                         return nil
119                 end
120         end
121
122         local data = {}
123
124         local tables = util.split(util.trim(rawdata), "\r?\n\r?\n", nil, true)
125
126
127         for i, tbl in ipairs(tables) do
128                 local lines = util.split(tbl, "\r?\n", nil, true)
129                 local name  = table.remove(lines, 1):sub(8)
130                 local keys  = util.split(table.remove(lines, 1), "\t")
131                 local split = #keys - 1
132
133                 data[name] = {}
134
135                 for j, line in ipairs(lines) do
136                         local fields = util.split(line, "\t", split)
137                         data[name][j] = {}
138                         for k, key in pairs(keys) do
139                                 data[name][j][key] = fields[k]
140                         end
141
142                         if data[name][j].Linkcost then
143                                 data[name][j].LinkQuality,
144                                 data[name][j].NLQ,
145                                 data[name][j].ETX =
146                                 data[name][j].Linkcost:match("([%w.]+)/([%w.]+)[%s]+([%w.]+)")
147                         end
148                 end
149         end
150
151         return data
152 end
153
154 function zeroes()
155         local string = require "string"
156         local http = require "luci.http"
157         local zeroes = string.rep(string.char(0), 8192)
158         local cnt = 0
159         local lim = 1024 * 1024 * 1024
160         
161         http.prepare_content("application/x-many-zeroes")
162
163         while cnt < lim do
164                 http.write(zeroes)
165                 cnt = cnt + #zeroes
166         end
167 end
168
169 function jsonstatus()
170         local root = {}
171         local sys = require "luci.sys"
172         local uci = require "luci.model.uci"
173         local util = require "luci.util"
174         local http = require "luci.http"
175         local json = require "luci.json"
176         local ltn12 = require "luci.ltn12"
177         local version = require "luci.version"
178         local webadmin = require "luci.tools.webadmin"
179
180         local cursor = uci.cursor_state()
181
182         local ffzone = webadmin.firewall_find_zone("freifunk")
183         local ffznet = ffzone and cursor:get("firewall", ffzone, "network")
184         local ffwifs = ffznet and util.split(ffznet, " ") or {}
185
186
187         root.protocol = 1
188
189         root.system = {
190                 uptime = {sys.uptime()},
191                 loadavg = {sys.loadavg()},
192                 sysinfo = {sys.sysinfo()},
193                 hostname = sys.hostname()
194         }
195
196         root.firmware = {
197                 luciname=version.luciname,
198                 luciversion=version.luciversion,
199                 distname=version.distname,
200                 distversion=version.distversion
201         }
202
203         root.freifunk = {}
204         cursor:foreach("freifunk", "public", function(s)
205                 root.freifunk[s[".name"]] = s
206         end)
207
208         cursor:foreach("system", "system", function(s)
209                 root.geo = {
210                         latitude = s.latitude,
211                         longitude = s.longitude
212                 }
213         end)
214
215         root.network = {}
216         root.wireless = {devices = {}, interfaces = {}, status = {}}
217         local wifs = root.wireless.interfaces
218         local wifidata = luci.sys.wifi.getiwconfig() or {}
219         local netdata = luci.sys.net.deviceinfo() or {}
220
221         for _, vif in ipairs(ffwifs) do
222                 root.network[vif] = cursor:get_all("network", vif)
223                 root.wireless.devices[vif] = cursor:get_all("wireless", vif)
224                 cursor:foreach("wireless", "wifi-iface", function(s)
225                         if s.device == vif and s.network == vif then
226                                 wifs[#wifs+1] = s
227                                 if s.ifname then
228                                         root.wireless.status[s.ifname] = wifidata[s.ifname]
229                                 end
230                         end
231                 end)
232         end
233
234         root.olsrd = fetch_olsrd()
235
236         http.prepare_content("application/json")
237         ltn12.pump.all(json.Encoder(root):source(), http.write)
238 end
239
240 function public_status_json()
241         local twa       = require "luci.tools.webadmin"
242         local sys       = require "luci.sys"
243         local i18n      = require "luci.i18n"
244         local path      = luci.dispatcher.context.requestpath
245         local rv        = { }
246
247         local dev
248         for dev in path[#path]:gmatch("[%w%.%-]+") do
249                 local j = { id = dev }
250                 local iw = luci.sys.wifi.getiwinfo(dev)
251                 if iw then
252                         local f
253                         for _, f in ipairs({
254                                 "channel", "txpower", "bitrate", "signal", "noise",
255                                 "quality", "quality_max", "mode", "ssid", "bssid", "encryption", "ifname"
256                         }) do
257                                 j[f] = iw[f]
258                         end
259                 end
260                 rv[#rv+1] = j
261         end
262
263         local load1, load5, load15 = sys.loadavg()
264
265         local  _, _, memtotal, memcached, membuffers, memfree = sys.sysinfo()
266         local mem = string.format("%.2f MB (%.2f %s, %.2f %s, %.2f %s, %.2f %s)",
267         tonumber(memtotal) / 1024,
268         tonumber(memtotal - memfree) / 1024,
269         tostring(i18n.translate("used")),
270         memfree / 1024,
271         tostring(i18n.translate("free")),
272         memcached / 1024,
273         tostring(i18n.translate("cached")),
274         membuffers / 1024,
275         tostring(i18n.translate("buffered"))
276         )
277
278         local dr4 = sys.net.defaultroute()
279         local dr6 = sys.net.defaultroute6()
280         
281         if dr6 then
282                 def6 = { 
283                 gateway = dr6.nexthop:string(),
284                 dest = dr6.dest:string(),
285                 dev = dr6.device,
286                 metr = dr6.metric }
287         end   
288
289         if dr4 then
290                 def4 = { 
291                 gateway = dr4.gateway:string(),
292                 dest = dr4.dest:string(),
293                 dev = dr4.device,
294                 metr = dr4.metric }
295         else
296                 local dr = sys.exec("ip r s t olsr-default")
297                 if dr then
298                         local dest, gateway, dev, metr = dr:match("^(%w+) via (%d+.%d+.%d+.%d+) dev (%w+) +metric (%d+)")
299                         def4 = {
300                                 dest = dest,
301                                 gateway = gateway,
302                                 dev = dev,
303                                 metr = metr
304                         }
305                 end
306         end
307         
308         rv[#rv+1] = {
309                 time = os.date("%a, %d %b %Y, %H:%M:%S"),
310                 uptime = twa.date_format(tonumber(sys.uptime())),
311                 load = string.format("%.2f, %.2f, %.2f", load1, load5, load15),
312                 mem = mem,
313                 defroutev4 = def4,
314                 defroutev6 = def6
315         }
316
317         luci.http.prepare_content("application/json")
318         luci.http.write_json(rv)
319         return
320 end