index.htm 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  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. uptime = wan6:uptime(),
  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><%:Address%>: </strong>%s<br />' +
  201. '<strong><%:Gateway%>: </strong>%s<br />',
  202. (ifc6.ip6addr) ? ifc6.ip6addr : '::',
  203. (ifc6.gw6addr) ? ifc6.gw6addr : '::'
  204. );
  205. for (var i = 0; i < ifc6.dns.length; i++)
  206. {
  207. s += String.format(
  208. '<strong><%:DNS%> %d: </strong>%s<br />',
  209. i + 1, ifc6.dns[i]
  210. );
  211. }
  212. if (ifc6.uptime > 0)
  213. {
  214. s += String.format(
  215. '<strong><%:Connected%>: </strong>%t<br />',
  216. ifc6.uptime
  217. );
  218. }
  219. ss6.innerHTML = String.format('<small>%s</small>', s);
  220. si6.innerHTML = String.format(
  221. '<img src="<%=resource%>/icons/ethernet.png" />' +
  222. '<br /><small><a href="%s">%s</a></small>',
  223. ifc6.link, ifc6.ifname
  224. );
  225. }
  226. else
  227. {
  228. si6.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
  229. ss6.innerHTML = '<em><%:Not connected%></em>';
  230. }
  231. <% end %>
  232. <% if has_dsl then %>
  233. var dsl_i = document.getElementById('dsl_i');
  234. var dsl_s = document.getElementById('dsl_s');
  235. var s = String.format(
  236. '<strong><%:Status%>: </strong>%s<br />' +
  237. '<strong><%:Line State%>: </strong>%s [0x%x]<br />' +
  238. '<strong><%:Line Mode%>: </strong>%s<br />' +
  239. '<strong><%:Annex%>: </strong>%s<br />' +
  240. '<strong><%:Profile%>: </strong>%s<br />' +
  241. '<strong><%:Data Rate%>: </strong>%s/s / %s/s<br />' +
  242. '<strong><%:Max. Attainable Data Rate (ATTNDR)%>: </strong>%s/s / %s/s<br />' +
  243. '<strong><%:Latency%>: </strong>%s / %s<br />' +
  244. '<strong><%:Line Attenuation (LATN)%>: </strong>%s dB / %s dB<br />' +
  245. '<strong><%:Signal Attenuation (SATN)%>: </strong>%s dB / %s dB<br />' +
  246. '<strong><%:Noise Margin (SNR)%>: </strong>%s dB / %s dB<br />' +
  247. '<strong><%:Aggregate Transmit Power(ACTATP)%>: </strong>%s dB / %s dB<br />' +
  248. '<strong><%:Forward Error Correction Seconds (FECS)%>: </strong>%s / %s<br />' +
  249. '<strong><%:Errored seconds (ES)%>: </strong>%s / %s<br />' +
  250. '<strong><%:Severely Errored Seconds (SES)%>: </strong>%s / %s<br />' +
  251. '<strong><%:Loss of Signal Seconds (LOSS)%>: </strong>%s / %s<br />' +
  252. '<strong><%:Unavailable Seconds (UAS)%>: </strong>%s / %s<br />' +
  253. '<strong><%:Header Error Code Errors (HEC)%>: </strong>%s / %s<br />' +
  254. '<strong><%:Non Pre-emtive CRC errors (CRC_P)%>: </strong>%s / %s<br />' +
  255. '<strong><%:Pre-emtive CRC errors (CRCP_P)%>: </strong>%s / %s<br />' +
  256. '<strong><%:Line Uptime%>: </strong>%s<br />' +
  257. '<strong><%:ATU-C System Vendor ID%>: </strong>%s<br />' +
  258. '<strong><%:Power Management Mode%>: </strong>%s<br />',
  259. info.dsl.line_state, info.dsl.line_state_detail,
  260. info.dsl.line_state_num,
  261. info.dsl.line_mode_s,
  262. info.dsl.annex_s,
  263. info.dsl.profile_s,
  264. info.dsl.data_rate_down_s, info.dsl.data_rate_up_s,
  265. info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s,
  266. info.dsl.latency_num_down, info.dsl.latency_num_up,
  267. info.dsl.line_attenuation_down, info.dsl.line_attenuation_up,
  268. info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up,
  269. info.dsl.noise_margin_down, info.dsl.noise_margin_up,
  270. info.dsl.actatp_down, info.dsl.actatp_up,
  271. info.dsl.errors_fec_near, info.dsl.errors_fec_far,
  272. info.dsl.errors_es_near, info.dsl.errors_es_far,
  273. info.dsl.errors_ses_near, info.dsl.errors_ses_far,
  274. info.dsl.errors_loss_near, info.dsl.errors_loss_far,
  275. info.dsl.errors_uas_near, info.dsl.errors_uas_far,
  276. info.dsl.errors_hec_near, info.dsl.errors_hec_far,
  277. info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far,
  278. info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far,
  279. info.dsl.line_uptime_s,
  280. info.dsl.atuc_vendor_id,
  281. info.dsl.power_mode_s
  282. );
  283. dsl_s.innerHTML = String.format('<small>%s</small>', s);
  284. dsl_i.innerHTML = String.format(
  285. '<img src="<%=resource%>/icons/ethernet.png" />' +
  286. '<br /><small>DSL</small>'
  287. );
  288. <% end %>
  289. <% if has_dhcp then %>
  290. var ls = document.getElementById('lease_status_table');
  291. if (ls)
  292. {
  293. /* clear all rows */
  294. while( ls.rows.length > 1 )
  295. ls.rows[0].parentNode.deleteRow(1);
  296. for( var i = 0; i < info.leases.length; i++ )
  297. {
  298. var timestr;
  299. if (info.leases[i].expires === false)
  300. timestr = '<em><%:unlimited%></em>';
  301. else if (info.leases[i].expires <= 0)
  302. timestr = '<em><%:expired%></em>';
  303. else
  304. timestr = String.format('%t', info.leases[i].expires);
  305. var tr = ls.rows[0].parentNode.insertRow(-1);
  306. tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
  307. tr.insertCell(-1).innerHTML = info.leases[i].hostname ? info.leases[i].hostname : '?';
  308. tr.insertCell(-1).innerHTML = info.leases[i].ipaddr;
  309. tr.insertCell(-1).innerHTML = info.leases[i].macaddr;
  310. tr.insertCell(-1).innerHTML = timestr;
  311. }
  312. if( ls.rows.length == 1 )
  313. {
  314. var tr = ls.rows[0].parentNode.insertRow(-1);
  315. tr.className = 'cbi-section-table-row';
  316. var td = tr.insertCell(-1);
  317. td.colSpan = 4;
  318. td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
  319. }
  320. }
  321. var ls6 = document.getElementById('lease6_status_table');
  322. if (ls6 && info.leases6)
  323. {
  324. ls6.parentNode.style.display = 'block';
  325. /* clear all rows */
  326. while( ls6.rows.length > 1 )
  327. ls6.rows[0].parentNode.deleteRow(1);
  328. for( var i = 0; i < info.leases6.length; i++ )
  329. {
  330. var timestr;
  331. if (info.leases6[i].expires === false)
  332. timestr = '<em><%:unlimited%></em>';
  333. else if (info.leases6[i].expires <= 0)
  334. timestr = '<em><%:expired%></em>';
  335. else
  336. timestr = String.format('%t', info.leases6[i].expires);
  337. var tr = ls6.rows[0].parentNode.insertRow(-1);
  338. tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
  339. var host = hosts[duid2mac(info.leases6[i].duid)];
  340. if (host)
  341. tr.insertCell(-1).innerHTML = String.format(
  342. '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
  343. ((host.name && (host.ipv4 || host.ipv6))
  344. ? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
  345. : '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
  346. );
  347. else
  348. tr.insertCell(-1).innerHTML = info.leases6[i].hostname ? info.leases6[i].hostname : '?';
  349. tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
  350. tr.insertCell(-1).innerHTML = info.leases6[i].duid;
  351. tr.insertCell(-1).innerHTML = timestr;
  352. }
  353. if( ls6.rows.length == 1 )
  354. {
  355. var tr = ls6.rows[0].parentNode.insertRow(-1);
  356. tr.className = 'cbi-section-table-row';
  357. var td = tr.insertCell(-1);
  358. td.colSpan = 4;
  359. td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
  360. }
  361. }
  362. <% end %>
  363. <% if has_wifi then %>
  364. var assoclist = [ ];
  365. var ws = document.getElementById('wifi_status_table');
  366. if (ws)
  367. {
  368. var wsbody = ws.rows[0].parentNode;
  369. while (ws.rows.length > 0)
  370. wsbody.deleteRow(0);
  371. for (var didx = 0; didx < info.wifinets.length; didx++)
  372. {
  373. var dev = info.wifinets[didx];
  374. var tr = wsbody.insertRow(-1);
  375. var td;
  376. td = tr.insertCell(-1);
  377. td.width = "33%";
  378. td.innerHTML = dev.name;
  379. td.style.verticalAlign = "top";
  380. td = tr.insertCell(-1);
  381. var s = '';
  382. for (var nidx = 0; nidx < dev.networks.length; nidx++)
  383. {
  384. var net = dev.networks[nidx];
  385. var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
  386. var icon;
  387. if (!is_assoc)
  388. icon = "<%=resource%>/icons/signal-none.png";
  389. else if (net.quality == 0)
  390. icon = "<%=resource%>/icons/signal-0.png";
  391. else if (net.quality < 25)
  392. icon = "<%=resource%>/icons/signal-0-25.png";
  393. else if (net.quality < 50)
  394. icon = "<%=resource%>/icons/signal-25-50.png";
  395. else if (net.quality < 75)
  396. icon = "<%=resource%>/icons/signal-50-75.png";
  397. else
  398. icon = "<%=resource%>/icons/signal-75-100.png";
  399. s += String.format(
  400. '<table><tr><td style="text-align:center; width:32px; padding:3px">' +
  401. '<img src="%s" title="<%:Signal%>: %d dBm / <%:Noise%>: %d dBm" />' +
  402. '<br /><small>%d%%</small>' +
  403. '</td><td style="text-align:left; padding:3px"><small>' +
  404. '<strong><%:SSID%>:</strong> <a href="%s">%h</a><br />' +
  405. '<strong><%:Mode%>:</strong> %s<br />' +
  406. '<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
  407. '<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%><br />',
  408. icon, net.signal, net.noise,
  409. net.quality,
  410. net.link, net.ssid || '?',
  411. net.mode,
  412. net.channel, net.frequency,
  413. net.bitrate || '?'
  414. );
  415. if (is_assoc)
  416. {
  417. s += String.format(
  418. '<strong><%:BSSID%>:</strong> %s<br />' +
  419. '<strong><%:Encryption%>:</strong> %s',
  420. net.bssid || '?',
  421. net.encryption
  422. );
  423. }
  424. else
  425. {
  426. s += '<em><%:Wireless is disabled or not associated%></em>';
  427. }
  428. s += '</small></td></tr></table>';
  429. for (var bssid in net.assoclist)
  430. {
  431. var bss = net.assoclist[bssid];
  432. bss.bssid = bssid;
  433. bss.link = net.link;
  434. bss.name = net.name;
  435. bss.ifname = net.ifname;
  436. bss.radio = dev.name;
  437. assoclist.push(bss);
  438. }
  439. }
  440. if (!s)
  441. s = '<em><%:No information available%></em>';
  442. td.innerHTML = s;
  443. }
  444. }
  445. var ac = document.getElementById('wifi_assoc_table');
  446. if (ac)
  447. {
  448. /* clear all rows */
  449. while( ac.rows.length > 1 )
  450. ac.rows[0].parentNode.deleteRow(1);
  451. assoclist.sort(function(a, b) {
  452. return (a.name == b.name)
  453. ? (a.bssid < b.bssid)
  454. : (a.name > b.name )
  455. ;
  456. });
  457. for( var i = 0; i < assoclist.length; i++ )
  458. {
  459. var tr = ac.rows[0].parentNode.insertRow(-1);
  460. tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
  461. var icon;
  462. var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5;
  463. if (q < 1)
  464. icon = "<%=resource%>/icons/signal-0.png";
  465. else if (q < 2)
  466. icon = "<%=resource%>/icons/signal-0-25.png";
  467. else if (q < 3)
  468. icon = "<%=resource%>/icons/signal-25-50.png";
  469. else if (q < 4)
  470. icon = "<%=resource%>/icons/signal-50-75.png";
  471. else
  472. icon = "<%=resource%>/icons/signal-75-100.png";
  473. tr.insertCell(-1).innerHTML = String.format(
  474. '<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
  475. assoclist[i].radio, assoclist[i].ifname
  476. );
  477. tr.insertCell(-1).innerHTML = String.format(
  478. '<a href="%s">%s</a>',
  479. assoclist[i].link,
  480. '%h'.format(assoclist[i].name).nobr()
  481. );
  482. tr.insertCell(-1).innerHTML = assoclist[i].bssid;
  483. var host = hosts[assoclist[i].bssid];
  484. if (host)
  485. tr.insertCell(-1).innerHTML = String.format(
  486. '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
  487. ((host.name && (host.ipv4 || host.ipv6))
  488. ? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
  489. : '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
  490. );
  491. else
  492. tr.insertCell(-1).innerHTML = '?';
  493. tr.insertCell(-1).innerHTML = String.format(
  494. '<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
  495. assoclist[i].signal, assoclist[i].noise, assoclist[i].signal - assoclist[i].noise,
  496. icon,
  497. assoclist[i].signal, assoclist[i].noise
  498. );
  499. tr.insertCell(-1).innerHTML = wifirate(assoclist[i], true).nobr() + '<br />' + wifirate(assoclist[i], false).nobr();
  500. }
  501. if (ac.rows.length == 1)
  502. {
  503. var tr = ac.rows[0].parentNode.insertRow(-1);
  504. tr.className = 'cbi-section-table-row';
  505. var td = tr.insertCell(-1);
  506. td.colSpan = 7;
  507. td.innerHTML = '<br /><em><%:No information available%></em>';
  508. }
  509. }
  510. <% end %>
  511. var e;
  512. if (e = document.getElementById('localtime'))
  513. e.innerHTML = info.localtime;
  514. if (e = document.getElementById('uptime'))
  515. e.innerHTML = String.format('%t', info.uptime);
  516. if (e = document.getElementById('loadavg'))
  517. e.innerHTML = String.format(
  518. '%.02f, %.02f, %.02f',
  519. info.loadavg[0] / 65535.0,
  520. info.loadavg[1] / 65535.0,
  521. info.loadavg[2] / 65535.0
  522. );
  523. if (e = document.getElementById('memtotal'))
  524. e.innerHTML = progressbar(
  525. ((info.memory.free + info.memory.buffered) / 1024) + " <%:kB%>",
  526. (info.memory.total / 1024) + " <%:kB%>"
  527. );
  528. if (e = document.getElementById('memfree'))
  529. e.innerHTML = progressbar(
  530. (info.memory.free / 1024) + " <%:kB%>",
  531. (info.memory.total / 1024) + " <%:kB%>"
  532. );
  533. if (e = document.getElementById('membuff'))
  534. e.innerHTML = progressbar(
  535. (info.memory.buffered / 1024) + " <%:kB%>",
  536. (info.memory.total / 1024) + " <%:kB%>"
  537. );
  538. if (e = document.getElementById('swaptotal'))
  539. e.innerHTML = progressbar(
  540. (info.swap.free / 1024) + " <%:kB%>",
  541. (info.swap.total / 1024) + " <%:kB%>"
  542. );
  543. if (e = document.getElementById('swapfree'))
  544. e.innerHTML = progressbar(
  545. (info.swap.free / 1024) + " <%:kB%>",
  546. (info.swap.total / 1024) + " <%:kB%>"
  547. );
  548. if (e = document.getElementById('conns'))
  549. e.innerHTML = progressbar(info.conncount, info.connmax);
  550. }
  551. );
  552. //]]></script>
  553. <h2 name="content"><%:Status%></h2>
  554. <fieldset class="cbi-section">
  555. <legend><%:System%></legend>
  556. <table width="100%" cellspacing="10">
  557. <tr><td width="33%"><%:Hostname%></td><td><%=luci.sys.hostname() or "?"%></td></tr>
  558. <tr><td width="33%"><%:Model%></td><td><%=pcdata(boardinfo.model or boardinfo.system or "?")%></td></tr>
  559. <tr><td width="33%"><%:Firmware Version%></td><td>
  560. <%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
  561. <%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
  562. </td></tr>
  563. <tr><td width="33%"><%:Kernel Version%></td><td><%=unameinfo.release or "?"%></td></tr>
  564. <tr><td width="33%"><%:Local Time%></td><td id="localtime">-</td></tr>
  565. <tr><td width="33%"><%:Uptime%></td><td id="uptime">-</td></tr>
  566. <tr><td width="33%"><%:Load Average%></td><td id="loadavg">-</td></tr>
  567. </table>
  568. </fieldset>
  569. <fieldset class="cbi-section">
  570. <legend><%:Memory%></legend>
  571. <table width="100%" cellspacing="10">
  572. <tr><td width="33%"><%:Total Available%></td><td id="memtotal">-</td></tr>
  573. <tr><td width="33%"><%:Free%></td><td id="memfree">-</td></tr>
  574. <tr><td width="33%"><%:Buffered%></td><td id="membuff">-</td></tr>
  575. </table>
  576. </fieldset>
  577. <% if swapinfo.total > 0 then %>
  578. <fieldset class="cbi-section">
  579. <legend><%:Swap%></legend>
  580. <table width="100%" cellspacing="10">
  581. <tr><td width="33%"><%:Total Available%></td><td id="swaptotal">-</td></tr>
  582. <tr><td width="33%"><%:Free%></td><td id="swapfree">-</td></tr>
  583. </table>
  584. </fieldset>
  585. <% end %>
  586. <fieldset class="cbi-section">
  587. <legend><%:Network%></legend>
  588. <table width="100%" cellspacing="10">
  589. <tr><td width="33%" style="vertical-align:top"><%:IPv4 WAN Status%></td><td>
  590. <table><tr>
  591. <td id="wan4_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
  592. <td id="wan4_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
  593. </tr></table>
  594. </td></tr>
  595. <% if has_ipv6 then %>
  596. <tr><td width="33%" style="vertical-align:top"><%:IPv6 WAN Status%></td><td>
  597. <table><tr>
  598. <td id="wan6_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
  599. <td id="wan6_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
  600. </tr></table>
  601. </td></tr>
  602. <% end %>
  603. <tr><td width="33%"><%:Active Connections%></td><td id="conns">-</td></tr>
  604. </table>
  605. </fieldset>
  606. <% if has_dhcp then %>
  607. <fieldset class="cbi-section">
  608. <legend><%:DHCP Leases%></legend>
  609. <table class="cbi-section-table" id="lease_status_table">
  610. <tr class="cbi-section-table-titles">
  611. <th class="cbi-section-table-cell"><%:Hostname%></th>
  612. <th class="cbi-section-table-cell"><%:IPv4-Address%></th>
  613. <th class="cbi-section-table-cell"><%:MAC-Address%></th>
  614. <th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
  615. </tr>
  616. <tr class="cbi-section-table-row">
  617. <td colspan="4"><em><br /><%:Collecting data...%></em></td>
  618. </tr>
  619. </table>
  620. </fieldset>
  621. <fieldset class="cbi-section" style="display:none">
  622. <legend><%:DHCPv6 Leases%></legend>
  623. <table class="cbi-section-table" id="lease6_status_table">
  624. <tr class="cbi-section-table-titles">
  625. <th class="cbi-section-table-cell"><%:Host%></th>
  626. <th class="cbi-section-table-cell"><%:IPv6-Address%></th>
  627. <th class="cbi-section-table-cell"><%:DUID%></th>
  628. <th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
  629. </tr>
  630. <tr class="cbi-section-table-row">
  631. <td colspan="4"><em><br /><%:Collecting data...%></em></td>
  632. </tr>
  633. </table>
  634. </fieldset>
  635. <% end %>
  636. <% if has_dsl then %>
  637. <fieldset class="cbi-section">
  638. <legend><%:DSL%></legend>
  639. <table width="100%" cellspacing="10">
  640. <tr><td width="33%" style="vertical-align:top"><%:DSL Status%></td><td>
  641. <table><tr>
  642. <td id="dsl_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
  643. <td id="dsl_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
  644. </tr></table>
  645. </td></tr>
  646. </table>
  647. </fieldset>
  648. <% end %>
  649. <% if has_wifi then %>
  650. <fieldset class="cbi-section">
  651. <legend><%:Wireless%></legend>
  652. <table id="wifi_status_table" width="100%" cellspacing="10">
  653. <tr><td><em><%:Collecting data...%></em></td></tr>
  654. </table>
  655. </fieldset>
  656. <fieldset class="cbi-section">
  657. <legend><%:Associated Stations%></legend>
  658. <table class="cbi-section-table valign-middle" id="wifi_assoc_table">
  659. <tr class="cbi-section-table-titles">
  660. <th class="cbi-section-table-cell">&#160;</th>
  661. <th class="cbi-section-table-cell"><%:Network%></th>
  662. <th class="cbi-section-table-cell"><%:MAC-Address%></th>
  663. <th class="cbi-section-table-cell"><%:Host%></th>
  664. <th class="cbi-section-table-cell"><%:Signal%> / <%:Noise%></th>
  665. <th class="cbi-section-table-cell"><%:RX Rate%> / <%:TX Rate%></th>
  666. </tr>
  667. <tr class="cbi-section-table-row">
  668. <td colspan="6"><em><br /><%:Collecting data...%></em></td>
  669. </tr>
  670. </table>
  671. </fieldset>
  672. <% end %>
  673. <%-
  674. local incdir = util.libpath() .. "/view/admin_status/index/"
  675. if fs.access(incdir) then
  676. local inc
  677. for inc in fs.dir(incdir) do
  678. if inc:match("%.htm$") then
  679. include("admin_status/index/" .. inc:gsub("%.htm$", ""))
  680. end
  681. end
  682. end
  683. -%>
  684. <%+footer%>