topology.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. 'use strict';
  2. 'require uci';
  3. 'require view';
  4. 'require poll';
  5. 'require rpc';
  6. 'require ui';
  7. function etx_color(etx) {
  8. let color = '#bb3333';
  9. if (etx === 0) {
  10. color = '#bb3333';
  11. } else if (etx < 2) {
  12. color = '#00cc00';
  13. } else if (etx < 4) {
  14. color = '#ffcb05';
  15. } else if (etx < 10) {
  16. color = '#ff6600';
  17. }
  18. return color;
  19. }
  20. return view.extend({
  21. callGetJsonStatus: rpc.declare({
  22. object: 'olsrinfo',
  23. method: 'getjsondata',
  24. params: ['otable', 'v4_port', 'v6_port'],
  25. }),
  26. fetch_jsoninfo: function (otable) {
  27. var jsonreq4 = '';
  28. var jsonreq6 = '';
  29. var v4_port = parseInt(uci.get('olsrd', 'olsrd_jsoninfo', 'port') || '') || 9090;
  30. var v6_port = parseInt(uci.get('olsrd6', 'olsrd_jsoninfo', 'port') || '') || 9090;
  31. var json;
  32. var self = this;
  33. return new Promise(function (resolve, reject) {
  34. L.resolveDefault(self.callGetJsonStatus(otable, v4_port, v6_port), {})
  35. .then(function (res) {
  36. json = res;
  37. jsonreq4 = JSON.parse(json.jsonreq4);
  38. jsonreq6 = json.jsonreq6 !== '' ? JSON.parse(json.jsonreq6) : [];
  39. var jsondata4 = {};
  40. var jsondata6 = {};
  41. var data4 = [];
  42. var data6 = [];
  43. var has_v4 = false;
  44. var has_v6 = false;
  45. if (jsonreq4 === '' && jsonreq6 === '') {
  46. window.location.href = 'error_olsr';
  47. reject([null, 0, 0, true]);
  48. return;
  49. }
  50. if (jsonreq4 !== '') {
  51. has_v4 = true;
  52. jsondata4 = jsonreq4 || {};
  53. if (otable === 'status') {
  54. data4 = jsondata4;
  55. } else {
  56. data4 = jsondata4[otable] || [];
  57. }
  58. for (var i = 0; i < data4.length; i++) {
  59. data4[i]['proto'] = '4';
  60. }
  61. }
  62. if (jsonreq6 !== '') {
  63. has_v6 = true;
  64. jsondata6 = jsonreq6 || {};
  65. if (otable === 'status') {
  66. data6 = jsondata6;
  67. } else {
  68. data6 = jsondata6[otable] || [];
  69. }
  70. for (var j = 0; j < data6.length; j++) {
  71. data6[j]['proto'] = '6';
  72. }
  73. }
  74. for (var k = 0; k < data6.length; k++) {
  75. data4.push(data6[k]);
  76. }
  77. resolve([data4, has_v4, has_v6, false]);
  78. })
  79. .catch(function (err) {
  80. console.error(err);
  81. reject([null, 0, 0, true]);
  82. });
  83. });
  84. },
  85. action_topology: function () {
  86. var self = this;
  87. return new Promise(function (resolve, reject) {
  88. self
  89. .fetch_jsoninfo('topology')
  90. .then(function ([data, has_v4, has_v6, error]) {
  91. if (error) {
  92. reject(error);
  93. }
  94. function compare(a, b) {
  95. if (a.proto === b.proto) {
  96. return a.tcEdgeCost < b.tcEdgeCost;
  97. } else {
  98. return a.proto < b.proto;
  99. }
  100. }
  101. data.sort(compare);
  102. var result = { routes: data, has_v4: has_v4, has_v6: has_v6 };
  103. resolve(result);
  104. })
  105. .catch(function (err) {
  106. reject(err);
  107. });
  108. });
  109. },
  110. load: function () {
  111. return Promise.all([uci.load('olsrd'), uci.load('luci_olsr')]);
  112. },
  113. render: function () {
  114. var routes_res;
  115. var has_v4;
  116. var has_v6;
  117. return this.action_topology()
  118. .then(function (result) {
  119. routes_res = result.routes;
  120. has_v4 = result.has_v4;
  121. has_v6 = result.has_v6;
  122. var table = E('div', { 'class': 'table cbi-section-table' }, [
  123. E('div', { 'class': 'tr cbi-section-table-titles' }, [
  124. E('div', { 'class': 'th cbi-section-table-cell' }, _('OLSR node')),
  125. E('div', { 'class': 'th cbi-section-table-cell' }, _('Last hop')),
  126. E('div', { 'class': 'th cbi-section-table-cell' }, _('LQ')),
  127. E('div', { 'class': 'th cbi-section-table-cell' }, _('NLQ')),
  128. E('div', { 'class': 'th cbi-section-table-cell' }, _('ETX')),
  129. ]),
  130. ]);
  131. var i = 1;
  132. for (var k = 0; k < routes_res.length; k++) {
  133. var route = routes_res[k];
  134. var cost = (parseInt(route.tcEdgeCost) || 0).toFixed(3);
  135. var color = etx_color(parseInt(cost));
  136. var lq = (parseInt(route.linkQuality) || 0).toFixed(3);
  137. var nlq = (parseInt(route.neighborLinkQuality) || 0).toFixed(3);
  138. var tr = E('div', { 'class': 'tr cbi-section-table-row cbi-rowstyle-' + i + ' proto-' + route.proto }, [
  139. route.proto === '6'
  140. ? E('div', { 'class': 'td cbi-section-table-cell left' }, [E('a', { 'href': 'http://[' + route.destinationIP + ']/cgi-bin-status.html' }, route.destinationIP)])
  141. : E('div', { 'class': 'td cbi-section-table-cell left' }, [E('a', { 'href': 'http://' + route.destinationIP + '/cgi-bin-status.html' }, route.destinationIP)]),
  142. route.proto === '6'
  143. ? E('div', { 'class': 'td cbi-section-table-cell left' }, [E('a', { 'href': 'http://[' + route.lastHopIP + ']/cgi-bin-status.html' }, route.lastHopIP)])
  144. : E('div', { 'class': 'td cbi-section-table-cell left' }, [E('a', { 'href': 'http://' + route.lastHopIP + '/cgi-bin-status.html' }, route.lastHopIP)]),
  145. E('div', { 'class': 'td cbi-section-table-cell left' }, lq),
  146. E('div', { 'class': 'td cbi-section-table-cell left' }, nlq),
  147. E('div', { 'class': 'td cbi-section-table-cell left', 'style': 'background-color:' + color }, cost),
  148. ]);
  149. table.appendChild(tr);
  150. i = (i % 2) + 1;
  151. }
  152. var fieldset = E('fieldset', { 'class': 'cbi-section' }, [E('legend', {}, _('Overview of currently known OLSR nodes')), table]);
  153. var h2 = E('h2', { 'name': 'content' }, _('Active OLSR nodes'));
  154. var divToggleButtons = E('div', { 'id': 'togglebuttons' });
  155. var statusOlsrLegend = E('div', {}, [
  156. E('h3', {}, [_('Legend') + ':']),
  157. E('ul', {}, [
  158. E('li', {}, [E('strong', {}, [_('LQ: ')]), _('Success rate of packages received from the neighbour')]),
  159. E('li', {}, [E('strong', {}, [_('NLQ: ')]), _('Success rate of packages sent to the neighbour')]),
  160. E('li', {}, [E('strong', {}, [_('ETX: ')]), _('Expected retransmission count')]),
  161. E('li', { style: 'list-style: none' }, [
  162. E('ul', {}, [
  163. E('li', {}, [E('strong', { 'style': 'color:#00cc00' }, [_('Green')]), ':', _('Very good (ETX < 2)')]),
  164. E('li', {}, [E('strong', { 'style': 'color:#ffcb05' }, [_('Yellow')]), ':', _('Good (2 < ETX < 4)')]),
  165. E('li', {}, [E('strong', { 'style': 'color:#ff6600' }, [_('Orange')]), ':', _('Still usable (4 < ETX < 10)')]),
  166. E('li', {}, [E('strong', { 'style': 'color:#bb3333' }, [_('Red')]), ':', _('Bad (ETX > 10)')]),
  167. ]),
  168. ]),
  169. E('li', {}, [E('strong', {}, [_('SNR: ')]), _('Signal Noise Ratio in dB')]),
  170. E('li', { 'style': 'list-style: none' }, [
  171. E('ul', {}, [
  172. E('li', {}, [E('strong', { 'style': 'color:#00cc00' }, [_('Green')]), ':', _('Very good (SNR > 30)')]),
  173. E('li', {}, [E('strong', { 'style': 'color:#ffcb05' }, [_('Yellow')]), ':', _('Good (30 > SNR > 20)')]),
  174. E('li', {}, [E('strong', { 'style': 'color:#ff6600' }, [_('Orange')]), ':', _('Still usable (20 > SNR > 5)')]),
  175. E('li', {}, [E('strong', { 'style': 'color:#bb3333' }, [_('Red')]), ':', _('Bad (SNR < 5)')]),
  176. ]),
  177. ]),
  178. ]),
  179. ]);
  180. var statusOlsrCommonJs = null;
  181. if (has_v4 && has_v6) {
  182. statusOlsrCommonJs = E('script', { 'type': 'text/javascript', 'src': L.resource('common/common_js.js') });
  183. }
  184. var result = E([], {}, [h2, divToggleButtons, fieldset, statusOlsrLegend, statusOlsrCommonJs]);
  185. return result;
  186. })
  187. .catch(function (error) {
  188. console.error(error);
  189. });
  190. },
  191. handleSaveApply: null,
  192. handleSave: null,
  193. handleReset: null,
  194. });