public_status.htm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <%
  2. local utl = require "luci.util"
  3. local sys = require "luci.sys"
  4. local twa = require "luci.tools.webadmin"
  5. local ip = require "luci.ip"
  6. -- System
  7. local sysinfo = utl.ubus("system", "info") or { }
  8. local boardinfo = utl.ubus("system", "board") or { }
  9. local loads = sysinfo.load or { 0, 0, 0 }
  10. local meminfo = sysinfo.memory or {
  11. total = 0,
  12. free = 0,
  13. buffered = 0,
  14. shared = 0
  15. }
  16. local uptime = twa.date_format(sysinfo.uptime or 0)
  17. local time = os.date("%a, %d %b %Y, %H:%M:%S")
  18. local load = string.format("%.2f, %.2f, %.2f", loads[1] / 65535.0, loads[2] / 65535.0, loads[3] / 65535.0)
  19. local mem = string.format(
  20. "%.2f MB (%.2f %s, %.2f %s, %.2f %s)",
  21. meminfo.total / 1024 / 1024,
  22. (meminfo.total - meminfo.free) / 1024 / 1024,
  23. tostring(i18n.translate("used")),
  24. meminfo.free / 1024 / 1024,
  25. tostring(i18n.translate("free")),
  26. meminfo.buffered / 1024 / 1024,
  27. tostring(i18n.translate("buffered"))
  28. )
  29. local interval = 5
  30. -- wireless
  31. local ntm = require "luci.model.network".init()
  32. local devices = ntm:get_wifidevs()
  33. local netlist = { }
  34. local netdevs = { }
  35. local dev
  36. for _, dev in ipairs(devices) do
  37. local net
  38. for _, net in ipairs(dev:get_wifinets()) do
  39. netlist[#netlist+1] = net:ifname()
  40. netdevs[net:ifname()] = dev:name()
  41. end
  42. end
  43. local has_iwinfo = pcall(require, "iwinfo")
  44. -- Find default routes
  45. local _, r, def4, def6
  46. for _, r in ipairs(ip.routes({ type = 1, dest_exact = "0.0.0.0/0" })) do
  47. def4 = {
  48. gateway = r.gw:string(),
  49. dest = r.dest:string(),
  50. dev = r.dev,
  51. metr = r.metric or 0
  52. }
  53. break
  54. end
  55. for _, r in ipairs(ip.routes({ type = 1, dest_exact = "::/0" })) do
  56. def6 = {
  57. gateway = r.gw:string(),
  58. dest = r.dest:string(),
  59. dev = r.dev,
  60. metr = r.metric or 0
  61. }
  62. break
  63. end
  64. if luci.http.formvalue("status") == "1" then
  65. local rv = { }
  66. for dev in pairs(netdevs) do
  67. local j = { id = dev }
  68. local iw = luci.sys.wifi.getiwinfo(dev)
  69. if iw then
  70. local f
  71. for _, f in ipairs({
  72. "channel", "txpower", "bitrate", "signal", "noise",
  73. "quality", "quality_max", "mode", "ssid", "bssid", "encryption", "ifname"
  74. }) do
  75. j[f] = iw[f]
  76. end
  77. end
  78. rv[#rv+1] = j
  79. end
  80. rv[#rv+1] = {
  81. time = time,
  82. uptime = uptime,
  83. load = load,
  84. mem = mem,
  85. defroutev4 = def4,
  86. defroutev6 = def6
  87. }
  88. luci.http.prepare_content("application/json")
  89. luci.http.write_json(rv)
  90. return
  91. end
  92. -%>
  93. <%+header%>
  94. <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
  95. <script type="text/javascript">//<![CDATA[
  96. XHR.poll(<%=interval%> , '<%=REQUEST_URI%>', { status: 1 },
  97. function(x, st)
  98. {
  99. if (st)
  100. {
  101. for( var i = 0; i < st.length; i++ )
  102. {
  103. var iw = st[i];
  104. var is_assoc = (iw.bssid && iw.channel);
  105. var p = (100 / iw.quality_max * iw.quality);
  106. var q = is_assoc ? p : -1;
  107. var icon;
  108. if (q < 0)
  109. icon = "<%=resource%>/icons/signal-none.png";
  110. else if (q == 0)
  111. icon = "<%=resource%>/icons/signal-0.png";
  112. else if (q < 25)
  113. icon = "<%=resource%>/icons/signal-0-25.png";
  114. else if (q < 50)
  115. icon = "<%=resource%>/icons/signal-25-50.png";
  116. else if (q < 75)
  117. icon = "<%=resource%>/icons/signal-50-75.png";
  118. else
  119. icon = "<%=resource%>/icons/signal-75-100.png";
  120. var power = document.getElementById(iw.id + '-txpower');
  121. if (power)
  122. power.innerHTML = String.format('%s dbm', iw.txpower);
  123. var signal = document.getElementById(iw.id + '-signal');
  124. if (signal)
  125. signal.innerHTML = String.format(
  126. '<img src="%s" title="Signal: %s db / Noise: %s db" alt="Signal Quality" />',
  127. icon, iw.signal, iw.noise
  128. );
  129. var bitrate = document.getElementById(iw.id + '-bitrate');
  130. if (bitrate)
  131. bitrate.innerHTML = String.format('%s Mb/s', iw.bitrate ? iw.bitrate / 1000 : '?');
  132. var ssid = document.getElementById(iw.id + '-ssid');
  133. if (ssid)
  134. ssid.innerHTML = iw.ssid;
  135. var bssid = document.getElementById(iw.id + '-bssid');
  136. if (bssid)
  137. bssid.innerHTML = iw.bssid;
  138. var channel = document.getElementById(iw.id + '-channel');
  139. if (channel)
  140. channel.innerHTML = iw.channel;
  141. var mode = document.getElementById(iw.id + '-mode');
  142. if (mode)
  143. mode.innerHTML = iw.mode;
  144. }
  145. i = st.length - 1
  146. var u
  147. if (u = document.getElementById('dynuptime'))
  148. u.innerHTML = st[i].uptime;
  149. if (u = document.getElementById('dynload'))
  150. u.innerHTML = st[i].load;
  151. if (u = document.getElementById('dynmem'))
  152. u.innerHTML = st[i].mem;
  153. if (u = document.getElementById('dyntime'))
  154. u.innerHTML = st[i].time;
  155. if (st[i].defroutev4)
  156. {
  157. if (u = document.getElementById('v4dst'))
  158. u.innerHTML = st[i].defroutev4.dest;
  159. if (u = document.getElementById('v4gw'))
  160. u.innerHTML = st[i].defroutev4.gateway;
  161. if (u = document.getElementById('v4dev'))
  162. u.innerHTML = st[i].defroutev4.dev;
  163. if (u = document.getElementById('v4metr'))
  164. u.innerHTML = st[i].defroutev4.metr;
  165. }
  166. if (st[i].defroutev6)
  167. {
  168. if (u = document.getElementById('v6dst'))
  169. u.innerHTML = st[i].defroutev6.dest;
  170. if (u = document.getElementById('v6gw'))
  171. u.innerHTML = st[i].defroutev6.gateway;
  172. if (u = document.getElementById('v6dev'))
  173. u.innerHTML = st[i].defroutev6.dev;
  174. if (u = document.getElementById('v6metr'))
  175. u.innerHTML = st[i].defroutev6.metr;
  176. }
  177. }
  178. }
  179. );
  180. //]]></script>
  181. <div class="cbi-map">
  182. <h2><%:System%></h2>
  183. <div class="cbi-section-node">
  184. <div class="cbi-value"><label class="cbi-value-title"><%:System%></label><div class="cbi-value-field"><%=boardinfo.system or "?"%></div></div>
  185. <div class="cbi-value"><label class="cbi-value-title"><%:Model%></label><div class="cbi-value-field"><%=boardinfo.model or "?"%></div></div>
  186. <div class="cbi-value"><label class="cbi-value-title"><%:Load%></label><div class="cbi-value-field" id="dynload"><%=load%></div></div>
  187. <div class="cbi-value"><label class="cbi-value-title"><%:Memory%></label><div class="cbi-value-field" id="dynmem"><%=mem%></div></div>
  188. <div class="cbi-value"><label class="cbi-value-title"><%:Local Time%></label><div class="cbi-value-field" id="dyntime"><%=time%></div></div>
  189. <div class="cbi-value"><label class="cbi-value-title"><%:Uptime%></label><div class="cbi-value-field" id="dynuptime"><%=uptime%></div></div>
  190. </div>
  191. </div>
  192. <% if devices[1] then %>
  193. <div class="cbi-map">
  194. <h2><%:Wireless Overview%></h2>
  195. <% if not has_iwinfo then %>
  196. <div class="errorbox">
  197. <strong><%:Package libiwinfo required!%></strong><br />
  198. <%_The <em>libiwinfo</em> package is not installed. You must install this component for working wireless configuration!%>
  199. </div>
  200. <% end %>
  201. <div class="cbi-section">
  202. <div class="cbi-section-node">
  203. <table class="cbi-section-table">
  204. <tr class="cbi-section-table-titles">
  205. <th class="cbi-section-table-cell"><%:Signal%></th>
  206. <th class="cbi-section-table-cell"><%:Bitrate%></th>
  207. <th class="cbi-section-table-cell"><%:SSID%></th>
  208. <th class="cbi-section-table-cell"><%:BSSID%></th>
  209. <th class="cbi-section-table-cell"><%:Channel%></th>
  210. <th class="cbi-section-table-cell"><%:Mode%></th>
  211. <th class="cbi-section-table-cell"><%:TX%>-<%:Power%></th>
  212. <th class="cbi-section-table-cell"><%:Interface%></th>
  213. </tr>
  214. <%
  215. for _, dev in ipairs(devices) do
  216. local net
  217. for _, net in ipairs(dev:get_wifinets()) do
  218. netlist[#netlist+1] = net:ifname()
  219. netdevs[net:ifname()] = dev:name()
  220. if net.iwinfo.signal and net.iwinfo.bssid then
  221. local signal = net.iwinfo.signal or "N/A"
  222. local noise = net.iwinfo.noise or "N/A"
  223. local q = net.iwinfo.quality or "0"
  224. local qmax = net.iwinfo.quality_max or "100"
  225. local qperc = q / qmax * 100
  226. if qperc == 0 then
  227. icon = "signal-none.png"
  228. elseif qperc < 26 then
  229. icon = "signal-0-25.png"
  230. elseif qperc < 51 then
  231. icon = "signal-25-50.png"
  232. elseif qperc < 76 then
  233. icon = "signal-50-75.png"
  234. elseif qperc < 100 then
  235. icon = "signal-75-100.png"
  236. else
  237. icon = "signal-0.png"
  238. end
  239. signal_string = "<img src='"..resource.."/icons/"..icon.."' title='Signal: "..signal.." db / Noise: "..noise.." db' alt='Signal Quality'></img>"
  240. local ssid = net.iwinfo.ssid or "N/A"
  241. local bssid = net.iwinfo.bssid or "N/A"
  242. local chan = net.iwinfo.channel or "N/A"
  243. local mode = net.iwinfo.mode or "N/A"
  244. local txpwr = net.iwinfo.txpower or "N/A"
  245. if txpwr ~= "N/A" then
  246. txpwr = txpwr.." dbm"
  247. end
  248. local bitrate = net.iwinfo.bitrate or "N/A"
  249. if bitrate ~= "N/A" then
  250. bitrate = ( bitrate / 1000 ).."Mb/s"
  251. end
  252. local interface = net.iwinfo.ifname or "N/A"
  253. %>
  254. <tr class="cbi-section-table-row cbi-rowstyle-1">
  255. <td class="cbi-value-field" id="<%=net:ifname()%>-signal"><%=signal_string%></td>
  256. <td class="cbi-value-field" id="<%=net:ifname()%>-bitrate"><%=bitrate%></td>
  257. <td class="cbi-value-field" id="<%=net:ifname()%>-ssid"><%=ssid%></td>
  258. <td class="cbi-value-field" id="<%=net:ifname()%>-bssid"><%=bssid%></td>
  259. <td class="cbi-value-field" id="<%=net:ifname()%>-channel"><%=chan%></td>
  260. <td class="cbi-value-field" id="<%=net:ifname()%>-mode"><%=mode%></td>
  261. <td class="cbi-value-field" id="<%=net:ifname()%>-txpower"><%=txpwr%></td>
  262. <td class="cbi-value-field"><%=interface%></td>
  263. </tr>
  264. <% end
  265. end
  266. end %>
  267. </table>
  268. </div>
  269. </div>
  270. </div>
  271. <% end %>
  272. <div class="cbi-map">
  273. <h2><%:Default routes%></h2>
  274. <div class="cbi-section">
  275. <div class="cbi-section-node">
  276. <% if not def4 and not def6 then %>
  277. <%:No default routes known.%>
  278. <%else%>
  279. <table class="cbi-section-table">
  280. <tr class="cbi-section-table-titles">
  281. <th class="cbi-section-table-cell"><%:Network%></th>
  282. <th class="cbi-section-table-cell"><%:Interface%></th>
  283. <th class="cbi-section-table-cell"><%:Gateway%></th>
  284. <th class="cbi-section-table-cell"><%:Metric%></th>
  285. </tr>
  286. <% if def4 then %>
  287. <tr class="cbi-section-table-row cbi-rowstyle-1">
  288. <td class="cbi-value-field" id="v4dst"><%=def4.dest%></td>
  289. <td class="cbi-value-field" id="v4dev"><%=def4.dev%></td>
  290. <td class="cbi-value-field" id="v4gw"><%=def4.gateway%></td>
  291. <td class="cbi-value-field" id="v4metr"><%=def4.metr%></td>
  292. </tr>
  293. <% end
  294. if def6 then %>
  295. <tr class="cbi-section-table-row cbi-rowstyle-2">
  296. <td class="cbi-value-field" id="v6dst"><%=def6.dest%></td>
  297. <td class="cbi-value-field" id="v6dev"><%=def6.dev%></td>
  298. <td class="cbi-value-field" id="v6gw"><%=def6.gateway%></td>
  299. <td class="cbi-value-field" id="v6metr"><%=def6.metr%></td>
  300. </tr>
  301. <% end %>
  302. </table>
  303. <% end %>
  304. </div>
  305. </div>
  306. </div>
  307. <%+footer%>