xref: /aosp_15_r20/external/ot-br-posix/src/openwrt/view/admin_thread/thread_overview.htm (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1<%-
2	local ubus = require "ubus"
3	local sys = require "luci.sys"
4	local utl = require "luci.util"
5
6	function connect_ubus(methods)
7		local result
8		local conn = ubus.connect()
9
10		if not conn then
11			error("Failed to connect to ubusd")
12		end
13
14		result = conn:call("otbr", methods, {})
15
16		return result
17	end
18
19	function threadget(action)
20		local result = connect_ubus(action)
21
22		return result
23	end
24-%>
25<%+header%>
26
27<h2><%:Thread Overview%></h2>
28<br />
29
30<div class="cbi-section-node">
31	<div class="table">
32		<!-- physical device -->
33		<div class="tr cbi-rowstyle-2">
34			<div class="td col-1 center middle">
35				<span class="ifacebadge"><img src="<%=resource .. "/icons/wifi.png"%>" id="wpan0" /> <%=threadget("interfacename").InterfaceName%></span>
36			</div>
37			<div class="td col-7 left middle">
38				<big><strong><%:Generic MAC 802.15.4 Thread%></strong></big><br />
39			</div>
40			<div class="td middle cbi-section-actions">
41				<div>
42					<div></div>
43					<form action="<%=url('admin/network/thread_scan')%>" method="post">
44						<input type="hidden" name="token" value="<%=token%>" />
45						<input type="submit" class="cbi-button cbi-button-action important" title="<%:Scan and join network%>" value="<%:Scan%>"/>
46					</form>
47					<form action="<%=url('admin/network/thread_create')%>" method="post">
48						<input type="hidden" name="token" value="<%=token%>" />
49						<input type="submit" class="cbi-button cbi-button-add" title="<%:Create new network%>" value="<%:Create%>"/>
50					</form>
51				</div>
52			</div>
53		</div>
54		<!-- /physical device -->
55
56		<!-- network list -->
57		<div class="tr cbi-rowstyle-1">
58			<div class="td col-1 center middle">
59			</div>
60			<div class="td col-7 left middle" id="status">
61				<em><%: Collecting data... %></em>
62			</div>
63			<div class="td middle cbi-section-actions">
64				<div id="action">
65				</div>
66			</div>
67		</div>
68		<!-- /network list -->
69	</div>
70</div>
71
72<br />
73<h2><%:Neighbors%></h2>
74<br />
75
76<div class="table" id="neighbors">
77	<div class="tr table-titles">
78		<div class="th col-2 center"><%:Signal%></div>
79		<div class="th col-1 center"><%:Role%></div>
80		<div class="th col-4 center"><%:RLOC16%></div>
81		<div class="th col-2 center"><%:Age%></div>
82		<div class="th col-2 center"><%:Avg RSSI%></div>
83		<div class="th col-2 center"><%:Last RSSI%></div>
84	</div>
85	<div class="tr placeholder">
86		<div class="td"><em><%:Collecting data...%></em></div>
87	</div>
88</div>
89
90<div class="table" id="parent" style="display:none;">
91	<div class="tr table-titles">
92		<div class="th col-2 center"><%:Signal%></div>
93		<div class="th col-1 center"><%:Role%></div>
94		<div class="th col-4 center"><%:RLOC16%></div>
95		<div class="th col-2 center"><%:Age%></div>
96		<div class="th col-2 center"><%:LinkQualityIn%></div>
97		<div class="th col-2 center"><%:ExtAddress%></div>
98	</div>
99	<div class="tr placeholder">
100		<div class="td"><em><%:Collecting data...%></em></div>
101	</div>
102</div>
103<%+footer%>
104
105<script type="text/javascript" src="/luci-static/resources/handle_error.js"></script>
106<script type="text/javascript">//<![CDATA[
107	handle_error(GetURLParameter('error'));
108
109	XHR.poll(2, '<%=url('admin/network/thread_state')%>', null,
110		function(x, st)
111		{
112			var sheet = document.getElementById('status');
113			var action = document.getElementById('action');
114			if (st && sheet && action)
115			{
116					if(st.state != "disabled")
117					{
118						sheet.innerHTML = String.format(
119							'<strong><%:Network Name: %></strong> %s<%: | %>' +
120							'<strong><%:State: %></strong>%s<br />' +
121							'<strong><%:PAN ID: %></strong>%s<%:   |   %>' +
122							'<strong><%:Channel: %></strong>%d<br />',
123								st.networkname, st.state, st.panid, st.channel
124						);
125						action.innerHTML = String.format(
126							'<form class="inline" action="<%=url('admin/network/thread_stop')%>" method="post">' +
127								'<input type="hidden" name="token" value="<%=token%>" />' +
128								'<input type="submit" class="cbi-button cbi-button-neutral" title="<%:Disable this network%>" value="<%:Disable%>" />' +
129							'</form>' +
130							'<form class="inline" action="<%=url('admin/network/thread_setting')%>" method="post">' +
131								'<input type="hidden" name="token" value="<%=token%>" />' +
132								'<input type="submit" class="cbi-button cbi-button-action important" title="<%:Edit this network%>" value="<%:Edit%>"/>' +
133							'</form>' +
134							'<form class="inline" action="<%=url('admin/network/thread_view')%>" method="post">' +
135								'<input type="hidden" name="token" value="<%=token%>" />' +
136								'<input type="submit" class="cbi-button cbi-button-add" title="<%:View this network%>" value="<%:View%>"/>' +
137							'</form>'
138						);
139					}
140					else
141					{
142						sheet.innerHTML = String.format(
143							'<strong><%:Not connect to any Thread network%></strong><br />' +
144							'<%: Please Join or Create a Thread network.%>'
145						);
146					}
147			}
148		});
149	function percent_thread_signal(info){
150		var linkquality = Number(info.LinkQualityIn);
151
152		if (linkquality == 0)
153			return 0;
154		else if (linkquality == 1)
155			return 30;
156		else if(linkquality == 2)
157			return 60;
158		else
159			return 100;
160	}
161
162	function guess_thread_signal(info) {
163		var icon;
164		var scale = percent_thread_signal(info);
165
166		if (scale == 0)
167			icon = "<%=resource%>/icons/signal-0.png";
168		else if (scale == 30)
169			icon = "<%=resource%>/icons/signal-25-50.png";
170		else if (scale == 50)
171			icon = "<%=resource%>/icons/signal-50-75.png";
172		else
173			icon = "<%=resource%>/icons/signal-75-100.png";
174
175		return icon;
176	}
177
178	XHR.poll(2, '<%=url('admin/network/thread_neighbors')%>', null,
179		function(x, st)
180		{
181			if(st && st.state == 'child')
182			{
183				var tb = document.getElementById('parent');
184				document.getElementById('neighbors').style.display = "none";
185				if (tb)
186				{
187					var rows = [];
188					st.neighbor.forEach(function(bss) {
189						var icon = guess_thread_signal(bss);
190						var signal = percent_thread_signal(bss);
191						rows.push([
192							'<abbr title="LinkQualityIn: %s"><img src="%s" /><br /><small> %s%</small></abbr>'.format(bss.LinkQualityIn, icon, signal),
193							'<div class="col-1 center"> %s </div>'.format(bss.Role),
194							'<div class="col-4 center"> %s </div>'.format(bss.Rloc16),
195							'<div class="col-2 center"> %s </div>'.format(bss.Age),
196							'<div class="col-2 center"> %s </div>'.format(bss.LinkQualityIn),
197							'<div class="col-2 center"> %s </div>'.format(bss.ExtAddress),
198						]);
199					});
200					cbi_update_table(tb, rows, '<center><em><%:No information available%></em></center>');
201					tb.style.display = "table";
202				}
203			}
204			else if(st)
205			{
206				var tb = document.getElementById('neighbors');
207				document.getElementById('parent').style.display = "none";
208				if (tb)
209				{
210					var rows = [];
211					st.neighbor.forEach(function(bss) {
212						var icon = guess_thread_signal(bss);
213						var signal = percent_thread_signal(bss);
214						rows.push([
215							'<abbr title="LinkQualityIn: %s"><img src="%s" /><br /><small> %s%</small></abbr>'.format(bss.LinkQualityIn, icon, signal),
216							'<div class="col-1 center"> %s </div>'.format(bss.Role),
217							'<div class="col-4 center"> %s </div>'.format(bss.Rloc16),
218							'<div class="col-2 center"> %s </div>'.format(bss.Age),
219							'<div class="col-2 center"> %s </div>'.format(bss.AvgRssi),
220							'<div class="col-2 center"> %s </div>'.format(bss.LastRssi),
221						]);
222					});
223					cbi_update_table(tb, rows, '<center><em><%:No information available%></em></center>');
224					tb.style.display = "table";
225				}
226			}
227		});
228//]]></script>
229