index.htm 25 KB

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