index.htm 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. <%#
  2. Copyright 2008 Steven Barth <steven@midlink.org>
  3. Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
  4. Licensed to the public under the Apache License 2.0.
  5. -%>
  6. <%
  7. local fs = require "nixio.fs"
  8. local util = require "luci.util"
  9. local stat = require "luci.tools.status"
  10. local ver = require "luci.version"
  11. local has_ipv6 = fs.access("/proc/net/ipv6_route")
  12. local has_dhcp = fs.access("/etc/config/dhcp")
  13. local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0)
  14. local sysinfo = luci.util.ubus("system", "info") or { }
  15. local boardinfo = luci.util.ubus("system", "board") or { }
  16. local unameinfo = nixio.uname() or { }
  17. local meminfo = sysinfo.memory or {
  18. total = 0,
  19. free = 0,
  20. buffered = 0,
  21. shared = 0
  22. }
  23. local swapinfo = sysinfo.swap or {
  24. total = 0,
  25. free = 0
  26. }
  27. local has_dsl = fs.access("/etc/init.d/dsl_control")
  28. if luci.http.formvalue("status") == "1" then
  29. local ntm = require "luci.model.network".init()
  30. local wan = ntm:get_wannet()
  31. local wan6 = ntm:get_wan6net()
  32. local conn_count = tonumber((
  33. luci.sys.exec("wc -l /proc/net/nf_conntrack") or
  34. luci.sys.exec("wc -l /proc/net/ip_conntrack") or
  35. ""):match("%d+")) or 0
  36. local conn_max = tonumber((
  37. luci.sys.exec("sysctl net.nf_conntrack_max") or
  38. luci.sys.exec("sysctl net.ipv4.netfilter.ip_conntrack_max") or
  39. ""):match("%d+")) or 4096
  40. local rv = {
  41. uptime = sysinfo.uptime or 0,
  42. localtime = os.date(),
  43. loadavg = sysinfo.load or { 0, 0, 0 },
  44. memory = meminfo,
  45. swap = swapinfo,
  46. connmax = conn_max,
  47. conncount = conn_count,
  48. leases = stat.dhcp_leases(),
  49. leases6 = stat.dhcp6_leases(),
  50. wifinets = stat.wifi_networks()
  51. }
  52. if wan then
  53. rv.wan = {
  54. ipaddr = wan:ipaddr(),
  55. gwaddr = wan:gwaddr(),
  56. netmask = wan:netmask(),
  57. dns = wan:dnsaddrs(),
  58. expires = wan:expires(),
  59. uptime = wan:uptime(),
  60. proto = wan:proto(),
  61. ifname = wan:ifname(),
  62. link = wan:adminlink()
  63. }
  64. end
  65. if wan6 then
  66. rv.wan6 = {
  67. ip6addr = wan6:ip6addr(),
  68. gw6addr = wan6:gw6addr(),
  69. dns = wan6:dns6addrs(),
  70. ip6prefix = wan6:ip6prefix(),
  71. uptime = wan6:uptime(),
  72. proto = wan6:proto(),
  73. ifname = wan6:ifname(),
  74. link = wan6:adminlink()
  75. }
  76. end
  77. if has_dsl then
  78. local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat")
  79. local dsl_func = loadstring(dsl_stat)
  80. if dsl_func then
  81. rv.dsl = dsl_func()
  82. end
  83. end
  84. luci.http.prepare_content("application/json")
  85. luci.http.write_json(rv)
  86. return
  87. elseif luci.http.formvalue("hosts") == "1" then
  88. luci.http.prepare_content("application/json")
  89. luci.http.write_json(luci.sys.net.host_hints())
  90. return
  91. end
  92. -%>
  93. <%+header%>
  94. <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
  95. <script type="text/javascript">//<![CDATA[
  96. function progressbar(v, m)
  97. {
  98. var vn = parseInt(v) || 0;
  99. var mn = parseInt(m) || 100;
  100. var pc = Math.floor((100 / mn) * vn);
  101. return String.format(
  102. '<div style="width:200px; position:relative; border:1px solid #999999">' +
  103. '<div style="background-color:#CCCCCC; width:%d%%; height:15px">' +
  104. '<div style="position:absolute; left:0; top:0; text-align:center; width:100%%; color:#000000">' +
  105. '<small>%s / %s (%d%%)</small>' +
  106. '</div>' +
  107. '</div>' +
  108. '</div>', pc, v, m, pc
  109. );
  110. }
  111. function wifirate(bss, rx) {
  112. var p = rx ? 'rx_' : 'tx_',
  113. s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
  114. .format(bss[p+'rate'] / 1000, bss[p+'mhz']),
  115. ht = bss[p+'ht'], vht = bss[p+'vht'],
  116. mhz = bss[p+'mhz'], nss = bss[p+'nss'],
  117. mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'];
  118. if (ht || vht) {
  119. if (vht) s += ', VHT-MCS %d'.format(mcs);
  120. if (nss) s += ', VHT-NSS %d'.format(nss);
  121. if (ht) s += ', MCS %s'.format(mcs);
  122. if (sgi) s += ', <%:Short GI%>';
  123. }
  124. return s;
  125. }
  126. function duid2mac(duid) {
  127. // DUID-LLT / Ethernet
  128. if (duid.length === 28 && duid.substr(0, 8) === '00010001')
  129. return duid.substr(16).replace(/(..)(?=..)/g, '$1:').toUpperCase();
  130. // DUID-LL / Ethernet
  131. if (duid.length === 24 && duid.substr(0, 8) === '00030001')
  132. return duid.substr(8).replace(/(..)(?=..)/g, '$1:').toUpperCase();
  133. return null;
  134. }
  135. var npoll = 1;
  136. var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
  137. function updateHosts() {
  138. XHR.get('<%=REQUEST_URI%>', { hosts: 1 }, function(x, data) {
  139. hosts = data;
  140. });
  141. }
  142. XHR.poll(5, '<%=REQUEST_URI%>', { status: 1 },
  143. function(x, info)
  144. {
  145. if (!(npoll++ % 5))
  146. updateHosts();
  147. var si = document.getElementById('wan4_i');
  148. var ss = document.getElementById('wan4_s');
  149. var ifc = info.wan;
  150. if (ifc && ifc.ifname && ifc.proto != 'none')
  151. {
  152. var s = String.format(
  153. '<strong><%:Type%>: </strong>%s<br />' +
  154. '<strong><%:Address%>: </strong>%s<br />' +
  155. '<strong><%:Netmask%>: </strong>%s<br />' +
  156. '<strong><%:Gateway%>: </strong>%s<br />',
  157. ifc.proto,
  158. (ifc.ipaddr) ? ifc.ipaddr : '0.0.0.0',
  159. (ifc.netmask && ifc.netmask != ifc.ipaddr) ? ifc.netmask : '255.255.255.255',
  160. (ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0'
  161. );
  162. for (var i = 0; i < ifc.dns.length; i++)
  163. {
  164. s += String.format(
  165. '<strong><%:DNS%> %d: </strong>%s<br />',
  166. i + 1, ifc.dns[i]
  167. );
  168. }
  169. if (ifc.expires > -1)
  170. {
  171. s += String.format(
  172. '<strong><%:Expires%>: </strong>%t<br />',
  173. ifc.expires
  174. );
  175. }
  176. if (ifc.uptime > 0)
  177. {
  178. s += String.format(
  179. '<strong><%:Connected%>: </strong>%t<br />',
  180. ifc.uptime
  181. );
  182. }
  183. ss.innerHTML = String.format('<small>%s</small>', s);
  184. si.innerHTML = String.format(
  185. '<img src="<%=resource%>/icons/ethernet.png" />' +
  186. '<br /><small><a href="%s">%s</a></small>',
  187. ifc.link, ifc.ifname
  188. );
  189. }
  190. else
  191. {
  192. si.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
  193. ss.innerHTML = '<em><%:Not connected%></em>';
  194. }
  195. <% if has_ipv6 then %>
  196. var si6 = document.getElementById('wan6_i');
  197. var ss6 = document.getElementById('wan6_s');
  198. var ifc6 = info.wan6;
  199. if (ifc6 && ifc6.ifname && ifc6.proto != 'none')
  200. {
  201. var s = String.format(
  202. '<strong><%:Type%>: </strong>%s%s<br />',
  203. ifc6.proto, (ifc6.ip6prefix) ? '-pd' : ''
  204. );
  205. if (!ifc6.ip6prefix)
  206. {
  207. s += String.format(
  208. '<strong><%:Address%>: </strong>%s<br />',
  209. (ifc6.ip6addr) ? ifc6.ip6addr : '::'
  210. );
  211. }
  212. else
  213. {
  214. s += String.format(
  215. '<strong><%:Prefix Delegated%>: </strong>%s<br />',
  216. ifc6.ip6prefix
  217. );
  218. if (ifc6.ip6addr)
  219. {
  220. s += String.format(
  221. '<strong><%:Address%>: </strong>%s<br />',
  222. ifc6.ip6addr
  223. );
  224. }
  225. }
  226. s += String.format(
  227. '<strong><%:Gateway%>: </strong>%s<br />',
  228. (ifc6.gw6addr) ? ifc6.gw6addr : '::'
  229. );
  230. for (var i = 0; i < ifc6.dns.length; i++)
  231. {
  232. s += String.format(
  233. '<strong><%:DNS%> %d: </strong>%s<br />',
  234. i + 1, ifc6.dns[i]
  235. );
  236. }
  237. if (ifc6.uptime > 0)
  238. {
  239. s += String.format(
  240. '<strong><%:Connected%>: </strong>%t<br />',
  241. ifc6.uptime
  242. );
  243. }
  244. ss6.innerHTML = String.format('<small>%s</small>', s);
  245. si6.innerHTML = String.format(
  246. '<img src="<%=resource%>/icons/ethernet.png" />' +
  247. '<br /><small><a href="%s">%s</a></small>',
  248. ifc6.link, ifc6.ifname
  249. );
  250. }
  251. else
  252. {
  253. si6.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
  254. ss6.innerHTML = '<em><%:Not connected%></em>';
  255. }
  256. <% end %>
  257. <% if has_dsl then %>
  258. var dsl_i = document.getElementById('dsl_i');
  259. var dsl_s = document.getElementById('dsl_s');
  260. var s = String.format(
  261. '<strong><%:Status%>: </strong>%s<br />' +
  262. '<strong><%:Line State%>: </strong>%s [0x%x]<br />' +
  263. '<strong><%:Line Mode%>: </strong>%s<br />' +
  264. '<strong><%:Annex%>: </strong>%s<br />' +
  265. '<strong><%:Profile%>: </strong>%s<br />' +
  266. '<strong><%:Data Rate%>: </strong>%s/s / %s/s<br />' +
  267. '<strong><%:Max. Attainable Data Rate (ATTNDR)%>: </strong>%s/s / %s/s<br />' +
  268. '<strong><%:Latency%>: </strong>%s / %s<br />' +
  269. '<strong><%:Line Attenuation (LATN)%>: </strong>%s dB / %s dB<br />' +
  270. '<strong><%:Signal Attenuation (SATN)%>: </strong>%s dB / %s dB<br />' +
  271. '<strong><%:Noise Margin (SNR)%>: </strong>%s dB / %s dB<br />' +
  272. '<strong><%:Aggregate Transmit Power(ACTATP)%>: </strong>%s dB / %s dB<br />' +
  273. '<strong><%:Forward Error Correction Seconds (FECS)%>: </strong>%s / %s<br />' +
  274. '<strong><%:Errored seconds (ES)%>: </strong>%s / %s<br />' +
  275. '<strong><%:Severely Errored Seconds (SES)%>: </strong>%s / %s<br />' +
  276. '<strong><%:Loss of Signal Seconds (LOSS)%>: </strong>%s / %s<br />' +
  277. '<strong><%:Unavailable Seconds (UAS)%>: </strong>%s / %s<br />' +
  278. '<strong><%:Header Error Code Errors (HEC)%>: </strong>%s / %s<br />' +
  279. '<strong><%:Non Pre-emtive CRC errors (CRC_P)%>: </strong>%s / %s<br />' +
  280. '<strong><%:Pre-emtive CRC errors (CRCP_P)%>: </strong>%s / %s<br />' +
  281. '<strong><%:Line Uptime%>: </strong>%s<br />' +
  282. '<strong><%:ATU-C System Vendor ID%>: </strong>%s<br />' +
  283. '<strong><%:Power Management Mode%>: </strong>%s<br />',
  284. info.dsl.line_state, info.dsl.line_state_detail,
  285. info.dsl.line_state_num,
  286. info.dsl.line_mode_s,
  287. info.dsl.annex_s,
  288. info.dsl.profile_s,
  289. info.dsl.data_rate_down_s, info.dsl.data_rate_up_s,
  290. info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s,
  291. info.dsl.latency_num_down, info.dsl.latency_num_up,
  292. info.dsl.line_attenuation_down, info.dsl.line_attenuation_up,
  293. info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up,
  294. info.dsl.noise_margin_down, info.dsl.noise_margin_up,
  295. info.dsl.actatp_down, info.dsl.actatp_up,
  296. info.dsl.errors_fec_near, info.dsl.errors_fec_far,
  297. info.dsl.errors_es_near, info.dsl.errors_es_far,
  298. info.dsl.errors_ses_near, info.dsl.errors_ses_far,
  299. info.dsl.errors_loss_near, info.dsl.errors_loss_far,
  300. info.dsl.errors_uas_near, info.dsl.errors_uas_far,
  301. info.dsl.errors_hec_near, info.dsl.errors_hec_far,
  302. info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far,
  303. info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far,
  304. info.dsl.line_uptime_s,
  305. info.dsl.atuc_vendor_id,
  306. info.dsl.power_mode_s
  307. );
  308. dsl_s.innerHTML = String.format('<small>%s</small>', s);
  309. dsl_i.innerHTML = String.format(
  310. '<img src="<%=resource%>/icons/ethernet.png" />' +
  311. '<br /><small>DSL</small>'
  312. );
  313. <% end %>
  314. <% if has_dhcp then %>
  315. var ls = document.getElementById('lease_status_table');
  316. if (ls)
  317. {
  318. /* clear all rows */
  319. while( ls.rows.length > 1 )
  320. ls.rows[0].parentNode.deleteRow(1);
  321. for( var i = 0; i < info.leases.length; i++ )
  322. {
  323. var timestr;
  324. if (info.leases[i].expires === false)
  325. timestr = '<em><%:unlimited%></em>';
  326. else if (info.leases[i].expires <= 0)
  327. timestr = '<em><%:expired%></em>';
  328. else
  329. timestr = String.format('%t', info.leases[i].expires);
  330. var tr = ls.rows[0].parentNode.insertRow(-1);
  331. tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
  332. tr.insertCell(-1).innerHTML = info.leases[i].hostname ? info.leases[i].hostname : '?';
  333. tr.insertCell(-1).innerHTML = info.leases[i].ipaddr;
  334. tr.insertCell(-1).innerHTML = info.leases[i].macaddr;
  335. tr.insertCell(-1).innerHTML = timestr;
  336. }
  337. if( ls.rows.length == 1 )
  338. {
  339. var tr = ls.rows[0].parentNode.insertRow(-1);
  340. tr.className = 'cbi-section-table-row';
  341. var td = tr.insertCell(-1);
  342. td.colSpan = 4;
  343. td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
  344. }
  345. }
  346. var ls6 = document.getElementById('lease6_status_table');
  347. if (ls6 && info.leases6)
  348. {
  349. ls6.parentNode.style.display = 'block';
  350. /* clear all rows */
  351. while( ls6.rows.length > 1 )
  352. ls6.rows[0].parentNode.deleteRow(1);
  353. for( var i = 0; i < info.leases6.length; i++ )
  354. {
  355. var timestr;
  356. if (info.leases6[i].expires === false)
  357. timestr = '<em><%:unlimited%></em>';
  358. else if (info.leases6[i].expires <= 0)
  359. timestr = '<em><%:expired%></em>';
  360. else
  361. timestr = String.format('%t', info.leases6[i].expires);
  362. var tr = ls6.rows[0].parentNode.insertRow(-1);
  363. tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
  364. var host = hosts[duid2mac(info.leases6[i].duid)];
  365. if (host)
  366. tr.insertCell(-1).innerHTML = String.format(
  367. '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
  368. ((host.name && (host.ipv4 || host.ipv6))
  369. ? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
  370. : '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
  371. );
  372. else
  373. tr.insertCell(-1).innerHTML = info.leases6[i].hostname ? info.leases6[i].hostname : '?';
  374. tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
  375. tr.insertCell(-1).innerHTML = info.leases6[i].duid;
  376. tr.insertCell(-1).innerHTML = timestr;
  377. }
  378. if( ls6.rows.length == 1 )
  379. {
  380. var tr = ls6.rows[0].parentNode.insertRow(-1);
  381. tr.className = 'cbi-section-table-row';
  382. var td = tr.insertCell(-1);
  383. td.colSpan = 4;
  384. td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
  385. }
  386. }
  387. <% end %>
  388. <% if has_wifi then %>
  389. var assoclist = [ ];
  390. var ws = document.getElementById('wifi_status_table');
  391. if (ws)
  392. {
  393. var wsbody = ws.rows[0].parentNode;
  394. while (ws.rows.length > 0)
  395. wsbody.deleteRow(0);
  396. for (var didx = 0; didx < info.wifinets.length; didx++)
  397. {
  398. var dev = info.wifinets[didx];
  399. var tr = wsbody.insertRow(-1);
  400. var td;
  401. td = tr.insertCell(-1);
  402. td.width = "33%";
  403. td.innerHTML = dev.name;
  404. td.style.verticalAlign = "top";
  405. td = tr.insertCell(-1);
  406. var s = '';
  407. for (var nidx = 0; nidx < dev.networks.length; nidx++)
  408. {
  409. var net = dev.networks[nidx];
  410. var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
  411. var icon;
  412. if (!is_assoc)
  413. icon = "<%=resource%>/icons/signal-none.png";
  414. else if (net.quality == 0)
  415. icon = "<%=resource%>/icons/signal-0.png";
  416. else if (net.quality < 25)
  417. icon = "<%=resource%>/icons/signal-0-25.png";
  418. else if (net.quality < 50)
  419. icon = "<%=resource%>/icons/signal-25-50.png";
  420. else if (net.quality < 75)
  421. icon = "<%=resource%>/icons/signal-50-75.png";
  422. else
  423. icon = "<%=resource%>/icons/signal-75-100.png";
  424. s += String.format(
  425. '<table><tr><td style="text-align:center; width:32px; padding:3px">' +
  426. '<img src="%s" title="<%:Signal%>: %d dBm / <%:Noise%>: %d dBm" />' +
  427. '<br /><small>%d%%</small>' +
  428. '</td><td style="text-align:left; padding:3px"><small>' +
  429. '<strong><%:SSID%>:</strong> <a href="%s">%h</a><br />' +
  430. '<strong><%:Mode%>:</strong> %s<br />' +
  431. '<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
  432. '<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%><br />',
  433. icon, net.signal, net.noise,
  434. net.quality,
  435. net.link, net.ssid || '?',
  436. net.mode,
  437. net.channel, net.frequency,
  438. net.bitrate || '?'
  439. );
  440. if (is_assoc)
  441. {
  442. s += String.format(
  443. '<strong><%:BSSID%>:</strong> %s<br />' +
  444. '<strong><%:Encryption%>:</strong> %s',
  445. net.bssid || '?',
  446. net.encryption
  447. );
  448. }
  449. else
  450. {
  451. s += '<em><%:Wireless is disabled or not associated%></em>';
  452. }
  453. s += '</small></td></tr></table>';
  454. for (var bssid in net.assoclist)
  455. {
  456. var bss = net.assoclist[bssid];
  457. bss.bssid = bssid;
  458. bss.link = net.link;
  459. bss.name = net.name;
  460. bss.ifname = net.ifname;
  461. bss.radio = dev.name;
  462. assoclist.push(bss);
  463. }
  464. }
  465. if (!s)
  466. s = '<em><%:No information available%></em>';
  467. td.innerHTML = s;
  468. }
  469. }
  470. var ac = document.getElementById('wifi_assoc_table');
  471. if (ac)
  472. {
  473. /* clear all rows */
  474. while( ac.rows.length > 1 )
  475. ac.rows[0].parentNode.deleteRow(1);
  476. assoclist.sort(function(a, b) {
  477. return (a.name == b.name)
  478. ? (a.bssid < b.bssid)
  479. : (a.name > b.name )
  480. ;
  481. });
  482. for( var i = 0; i < assoclist.length; i++ )
  483. {
  484. var tr = ac.rows[0].parentNode.insertRow(-1);
  485. tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
  486. var icon;
  487. var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5;
  488. if (q < 1)
  489. icon = "<%=resource%>/icons/signal-0.png";
  490. else if (q < 2)
  491. icon = "<%=resource%>/icons/signal-0-25.png";
  492. else if (q < 3)
  493. icon = "<%=resource%>/icons/signal-25-50.png";
  494. else if (q < 4)
  495. icon = "<%=resource%>/icons/signal-50-75.png";
  496. else
  497. icon = "<%=resource%>/icons/signal-75-100.png";
  498. tr.insertCell(-1).innerHTML = String.format(
  499. '<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
  500. assoclist[i].radio, assoclist[i].ifname
  501. );
  502. tr.insertCell(-1).innerHTML = String.format(
  503. '<a href="%s">%s</a>',
  504. assoclist[i].link,
  505. '%h'.format(assoclist[i].name).nobr()
  506. );
  507. tr.insertCell(-1).innerHTML = assoclist[i].bssid;
  508. var host = hosts[assoclist[i].bssid];
  509. if (host)
  510. tr.insertCell(-1).innerHTML = String.format(
  511. '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
  512. ((host.name && (host.ipv4 || host.ipv6))
  513. ? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
  514. : '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
  515. );
  516. else
  517. tr.insertCell(-1).innerHTML = '?';
  518. tr.insertCell(-1).innerHTML = String.format(
  519. '<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
  520. assoclist[i].signal, assoclist[i].noise, assoclist[i].signal - assoclist[i].noise,
  521. icon,
  522. assoclist[i].signal, assoclist[i].noise
  523. );
  524. tr.insertCell(-1).innerHTML = wifirate(assoclist[i], true).nobr() + '<br />' + wifirate(assoclist[i], false).nobr();
  525. }
  526. if (ac.rows.length == 1)
  527. {
  528. var tr = ac.rows[0].parentNode.insertRow(-1);
  529. tr.className = 'cbi-section-table-row';
  530. var td = tr.insertCell(-1);
  531. td.colSpan = 7;
  532. td.innerHTML = '<br /><em><%:No information available%></em>';
  533. }
  534. }
  535. <% end %>
  536. var e;
  537. if (e = document.getElementById('localtime'))
  538. e.innerHTML = info.localtime;
  539. if (e = document.getElementById('uptime'))
  540. e.innerHTML = String.format('%t', info.uptime);
  541. if (e = document.getElementById('loadavg'))
  542. e.innerHTML = String.format(
  543. '%.02f, %.02f, %.02f',
  544. info.loadavg[0] / 65535.0,
  545. info.loadavg[1] / 65535.0,
  546. info.loadavg[2] / 65535.0
  547. );
  548. if (e = document.getElementById('memtotal'))
  549. e.innerHTML = progressbar(
  550. ((info.memory.free + info.memory.buffered) / 1024) + " <%:kB%>",
  551. (info.memory.total / 1024) + " <%:kB%>"
  552. );
  553. if (e = document.getElementById('memfree'))
  554. e.innerHTML = progressbar(
  555. (info.memory.free / 1024) + " <%:kB%>",
  556. (info.memory.total / 1024) + " <%:kB%>"
  557. );
  558. if (e = document.getElementById('membuff'))
  559. e.innerHTML = progressbar(
  560. (info.memory.buffered / 1024) + " <%:kB%>",
  561. (info.memory.total / 1024) + " <%:kB%>"
  562. );
  563. if (e = document.getElementById('swaptotal'))
  564. e.innerHTML = progressbar(
  565. (info.swap.free / 1024) + " <%:kB%>",
  566. (info.swap.total / 1024) + " <%:kB%>"
  567. );
  568. if (e = document.getElementById('swapfree'))
  569. e.innerHTML = progressbar(
  570. (info.swap.free / 1024) + " <%:kB%>",
  571. (info.swap.total / 1024) + " <%:kB%>"
  572. );
  573. if (e = document.getElementById('conns'))
  574. e.innerHTML = progressbar(info.conncount, info.connmax);
  575. }
  576. );
  577. //]]></script>
  578. <h2 name="content"><%:Status%></h2>
  579. <fieldset class="cbi-section">
  580. <legend><%:System%></legend>
  581. <table width="100%" cellspacing="10">
  582. <tr><td width="33%"><%:Hostname%></td><td><%=luci.sys.hostname() or "?"%></td></tr>
  583. <tr><td width="33%"><%:Model%></td><td><%=pcdata(boardinfo.model or boardinfo.system or "?")%></td></tr>
  584. <tr><td width="33%"><%:Firmware Version%></td><td>
  585. <%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
  586. <%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
  587. </td></tr>
  588. <tr><td width="33%"><%:Kernel Version%></td><td><%=unameinfo.release or "?"%></td></tr>
  589. <tr><td width="33%"><%:Local Time%></td><td id="localtime">-</td></tr>
  590. <tr><td width="33%"><%:Uptime%></td><td id="uptime">-</td></tr>
  591. <tr><td width="33%"><%:Load Average%></td><td id="loadavg">-</td></tr>
  592. </table>
  593. </fieldset>
  594. <fieldset class="cbi-section">
  595. <legend><%:Memory%></legend>
  596. <table width="100%" cellspacing="10">
  597. <tr><td width="33%"><%:Total Available%></td><td id="memtotal">-</td></tr>
  598. <tr><td width="33%"><%:Free%></td><td id="memfree">-</td></tr>
  599. <tr><td width="33%"><%:Buffered%></td><td id="membuff">-</td></tr>
  600. </table>
  601. </fieldset>
  602. <% if swapinfo.total > 0 then %>
  603. <fieldset class="cbi-section">
  604. <legend><%:Swap%></legend>
  605. <table width="100%" cellspacing="10">
  606. <tr><td width="33%"><%:Total Available%></td><td id="swaptotal">-</td></tr>
  607. <tr><td width="33%"><%:Free%></td><td id="swapfree">-</td></tr>
  608. </table>
  609. </fieldset>
  610. <% end %>
  611. <fieldset class="cbi-section">
  612. <legend><%:Network%></legend>
  613. <table width="100%" cellspacing="10">
  614. <tr><td width="33%" style="vertical-align:top"><%:IPv4 WAN Status%></td><td>
  615. <table><tr>
  616. <td id="wan4_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
  617. <td id="wan4_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
  618. </tr></table>
  619. </td></tr>
  620. <% if has_ipv6 then %>
  621. <tr><td width="33%" style="vertical-align:top"><%:IPv6 WAN Status%></td><td>
  622. <table><tr>
  623. <td id="wan6_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
  624. <td id="wan6_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
  625. </tr></table>
  626. </td></tr>
  627. <% end %>
  628. <tr><td width="33%"><%:Active Connections%></td><td id="conns">-</td></tr>
  629. </table>
  630. </fieldset>
  631. <% if has_dhcp then %>
  632. <fieldset class="cbi-section">
  633. <legend><%:DHCP Leases%></legend>
  634. <table class="cbi-section-table" id="lease_status_table">
  635. <tr class="cbi-section-table-titles">
  636. <th class="cbi-section-table-cell"><%:Hostname%></th>
  637. <th class="cbi-section-table-cell"><%:IPv4-Address%></th>
  638. <th class="cbi-section-table-cell"><%:MAC-Address%></th>
  639. <th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
  640. </tr>
  641. <tr class="cbi-section-table-row">
  642. <td colspan="4"><em><br /><%:Collecting data...%></em></td>
  643. </tr>
  644. </table>
  645. </fieldset>
  646. <fieldset class="cbi-section" style="display:none">
  647. <legend><%:DHCPv6 Leases%></legend>
  648. <table class="cbi-section-table" id="lease6_status_table">
  649. <tr class="cbi-section-table-titles">
  650. <th class="cbi-section-table-cell"><%:Host%></th>
  651. <th class="cbi-section-table-cell"><%:IPv6-Address%></th>
  652. <th class="cbi-section-table-cell"><%:DUID%></th>
  653. <th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
  654. </tr>
  655. <tr class="cbi-section-table-row">
  656. <td colspan="4"><em><br /><%:Collecting data...%></em></td>
  657. </tr>
  658. </table>
  659. </fieldset>
  660. <% end %>
  661. <% if has_dsl then %>
  662. <fieldset class="cbi-section">
  663. <legend><%:DSL%></legend>
  664. <table width="100%" cellspacing="10">
  665. <tr><td width="33%" style="vertical-align:top"><%:DSL Status%></td><td>
  666. <table><tr>
  667. <td id="dsl_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
  668. <td id="dsl_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
  669. </tr></table>
  670. </td></tr>
  671. </table>
  672. </fieldset>
  673. <% end %>
  674. <% if has_wifi then %>
  675. <fieldset class="cbi-section">
  676. <legend><%:Wireless%></legend>
  677. <table id="wifi_status_table" width="100%" cellspacing="10">
  678. <tr><td><em><%:Collecting data...%></em></td></tr>
  679. </table>
  680. </fieldset>
  681. <fieldset class="cbi-section">
  682. <legend><%:Associated Stations%></legend>
  683. <table class="cbi-section-table valign-middle" id="wifi_assoc_table">
  684. <tr class="cbi-section-table-titles">
  685. <th class="cbi-section-table-cell">&#160;</th>
  686. <th class="cbi-section-table-cell"><%:Network%></th>
  687. <th class="cbi-section-table-cell"><%:MAC-Address%></th>
  688. <th class="cbi-section-table-cell"><%:Host%></th>
  689. <th class="cbi-section-table-cell"><%:Signal%> / <%:Noise%></th>
  690. <th class="cbi-section-table-cell"><%:RX Rate%> / <%:TX Rate%></th>
  691. </tr>
  692. <tr class="cbi-section-table-row">
  693. <td colspan="6"><em><br /><%:Collecting data...%></em></td>
  694. </tr>
  695. </table>
  696. </fieldset>
  697. <% end %>
  698. <%-
  699. local incdir = util.libpath() .. "/view/admin_status/index/"
  700. if fs.access(incdir) then
  701. local inc
  702. for inc in fs.dir(incdir) do
  703. if inc:match("%.htm$") then
  704. include("admin_status/index/" .. inc:gsub("%.htm$", ""))
  705. end
  706. end
  707. end
  708. -%>
  709. <%+footer%>