1 <!DOCTYPE html>
2 <html lang="en">
3 <!--
4 /******************************************************************************
6 @file collectorApp.html
8 @brief front end file
10 Group: WCS LPC
11 $Target Devices: Linux: AM335x, Embedded Devices: CC1310, CC1350$
13 ******************************************************************************
14 $License: BSD3 2016 $
16 Copyright (c) 2015, Texas Instruments Incorporated
17 All rights reserved.
19 Redistribution and use in source and binary forms, with or without
20 modification, are permitted provided that the following conditions
21 are met:
23 * Redistributions of source code must retain the above copyright
24 notice, this list of conditions and the following disclaimer.
26 * Redistributions in binary form must reproduce the above copyright
27 notice, this list of conditions and the following disclaimer in the
28 documentation and/or other materials provided with the distribution.
30 * Neither the name of Texas Instruments Incorporated nor the names of
31 its contributors may be used to endorse or promote products derived
32 from this software without specific prior written permission.
34 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
35 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
36 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
38 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
41 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
43 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
44 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 ******************************************************************************
46 $Release Name: TI-15.4Stack Linux x64 SDK ENG$
47 $Release Date: Nov 21, 2016 (2.00.01.09)$
48 *****************************************************************************/
49 -->
51 <head>
52 <meta charset="utf-8">
53 <meta http-equiv="X-UA-Compatible" content="IE=edge">
54 <meta name="viewport" content="width=device-width, initial-scale=1">
55 <!-- The above 3 meta tags *must* come first in the head; any other
56 head content must come *after* these tags -->
57 <meta name="description" content="">
58 <meta name="author" content="Brock Allen">
60 <title>Sensor-To-Cloud Gateway</title>
61 <!-- Bootstrap core CSS -->
62 <link href="dist/css/bootstrap.min.css" rel="stylesheet">
64 <style>
65 /* Sets the device information block to scroll after
66 set height */
68 #ConnectedDeviceWrapper {
69 max-height: 400px;
70 overflow-y: auto;
71 }
73 /* set alignment for table elements */
75 .table>tbody>tr>td {
76 vertical-align: middle;
77 }
78 </style>
79 </head>
81 <body>
82 <nav class="navbar navbar-inverse navbar-fixed-top">
83 <div class="navbar-header">
84 <a class="navbar-brand" href="#">TI 15.4-Stack Sensor-To-Cloud Gateway</a>
85 <ul class="nav navbar-nav navbar-right">
86 <!-- Button trigger modal -->
87 <li>
88 <!--<a class=" glyphicon glyphicon-cog" data-toggle="modal" data-target="#myModalNorm"></a>-->
89 </li>
90 </ul>
91 </div>
92 </nav>
94 <!-- Modal -->
95 <div class="modal fade" id="myModalNorm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
96 <div class="modal-dialog">
97 <div class="modal-content">
98 <!-- Modal Header -->
99 <div class="modal-header">
100 <button type="button" class="close" data-dismiss="modal">
101 <span aria-hidden="true">×</span>
102 <span class="sr-only">Close</span>
103 </button>
104 <h4 class="modal-title" id="myModalLabel">
105 IBM IoT Credentials
106 </h4>
107 </div>
109 <!-- Modal Body -->
110 <div class="modal-body">
112 <form role="form">
113 <div class="form-group">
114 <label for="ServiceName">Service Name</label>
115 <input type="text" class="form-control" id="ServiceName" placeholder="Enter Service Name" />
116 </div>
117 <div class="form-group">
118 <label for="Id">ID</label>
119 <input type="text" class="form-control" id="Id" placeholder="Enter iot Credentials Identifier" />
120 </div>
121 <div class="form-group">
122 <label for="Org">Org</label>
123 <input type="text" class="form-control" id="Org" placeholder="Enter org" />
124 </div>
125 <div class="form-group">
126 <label for="ApiKey">API Key</label>
127 <input type="text" class="form-control" id="ApiKey" placeholder="Enter api Key" />
128 </div>
129 <div class="form-group">
130 <label for="ApiToken">API Token</label>
131 <input type="text" class="form-control" id="ApiToken" placeholder="Enter api Token" />
132 </div>
133 <div class="form-group">
134 <label for="type">Device Type</label>
135 <input type="text" class="form-control" id="type" placeholder="Enter Device Type" />
136 </div>
137 <div class="form-group">
138 <label for="typeId">Device ID</label>
139 <input type="text" class="form-control" id="typeId" placeholder="Enter Device Id" />
140 </div>
142 <div class="modal-footer">
143 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
144 <input id="changeBtn" type="button" class="btn btn-primary" value="Save changes" data-dismiss="modal" />
145 </div>
146 </form>
147 </div>
148 </div>
149 </div>
150 </div>
152 <!-- Main jumbotron -->
153 <div class="jumbotron">
154 <div class="container">
155 <h2>TI 15.4-Stack Linux Gateway Example Application</h2>
156 </div>
157 </div>
159 <div class="container">
160 <!--main data -->
161 <div class="row">
162 <div class="col-md-4">
163 <div id="networkInformationWrapper">
164 <div class="panel-group">
165 <div class="panel panel-default">
166 <div class="panel-heading">
167 <h4>
168 <b>Network Information</b>
169 </h4>
170 </div>
171 <!-- h2 >Network Information</h2 -->
172 <table class="table table-hover table-responsive nwkInformationTable">
173 <tr>
174 <td>PanID</td>
175 <td>
176 <span id="panid"></span>
177 </td>
178 </tr>
179 <tr>
180 <td>Coord Addr</td>
181 <td>
182 <span id="coordAddr"></span>
183 </td>
184 </tr>
185 <tr>
186 <td>Network Mode</td>
187 <td>
188 <span id="networkmode"></span>
189 </td>
190 </tr>
191 <tr>
192 <td>Security</td>
193 <td>
194 <span id="security"></span>
195 </td>
196 </tr>
197 <tr class="networkstate">
198 <td id="nwkStateText">
199 Network close for New Devices
200 </td>
201 <td>
202 <button type=button class=btn btn-default id="allowJoin">open</button>
203 </td>
204 <td>
205 <span id="nwkJoinCountdown"></span>
206 </td>
207 </tr>
208 </table>
209 </div>
210 </div>
211 </div>
213 <div>
214 <div class="panel-group">
215 <div class="panel panel-default">
216 <div id="networkConvasPanel" class="panel-heading">
217 <h4>
218 <b>Network</b>
219 </h4>
220 </div>
221 <canvas id="networkCanvas" class="canvas"></canvas>
222 </div>
223 </div>
224 </div>
225 </div>
227 <div class="col-md-8">
228 <!-- Device List Information Box -->
229 <div class="panel-group">
230 <div class="panel panel-default">
231 <div class="panel-heading">
232 <h4>
233 <b>Sensor Nodes</b>
234 </h4>
235 </div>
236 <table class="table table-hover table-responsive">
237 <tr>
238 <th class="text-left">Device Info</th>
239 <th class="text-center">Sensors Data</th>
240 <th class="text-center">Action</th>
241 </tr>
242 </table>
243 <div id="ConnectedDeviceWrapper">
244 <table id="deviceTable" class="table table-hover table-responsive ">
245 </table>
246 </div>
247 </div>
248 </div>
249 </div>
250 </div>
252 <footer>
253 <p>© 2016-17 Texas Instruments Incorporated.</p>
254 </footer>
255 </div>
256 <!-- /container -->
257 <!-- Bootstrap core JavaScript
258 ================================================== -->
259 <!-- Placed at the end of the document so the pages load faster -->
260 <script src="/dist/jquery/jquery-1.12.0.min.js"></script>
261 <script>
262 window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')
263 </script>
264 <script src="dist/js/bootstrap.min.js"></script>
265 <script src="/socket.io/socket.io.js"></script>
266 <script>
267 const Smsgs_dataFields = Object.freeze({
268 tempSensor: 0x0001,
269 lightSensor: 0x0002,
270 humiditySensor: 0x0004,
271 msgStats: 0x0008,
272 configSettings: 0x0010,
273 pressureSensor: 0x0020,
274 motionSensor: 0x0040,
275 batteryVoltageSensor: 0x0080,
276 hallEffectSensor: 0x0100,
277 fanSensor: 0x0200,
278 doorLockSensor: 0x0400,
279 waterLeakSensor: 0x0800
280 });
282 const dIn_iid = Object.freeze({
283 motion: 0,
284 hallEffectOpen: 1,
285 hallEffectTampered: 2,
286 doorLock: 3,
287 waterLeak: 4
288 });
290 const temperature_iid = Object.freeze({
291 ambienceTemp: 0,
292 objectTemp: 1,
293 humidityTemp: 2,
294 pressureTemp: 3
295 });
297 const illuminance_iid = Object.freeze({
298 lightSensor: 0
299 });
301 const humidity_iid = Object.freeze({
302 humiditySensor: 0
303 });
305 const barometer_iid = Object.freeze({
306 pressureSensor: 0
307 });
309 const actuator_iid = Object.freeze({
310 fan: 0
311 });
313 const generic_iid = Object.freeze({
314 batteryVoltage: 0
315 });
316 $(function () {
317 var socket = io.connect();
318 /* Device table */
319 var $deviceTable = $('#deviceTable');
321 /* Network Information Block */
322 var $panid = $('#panid');
323 var $coordAddr = $('#coordAddr');
324 var $security = $('#security');
325 var $networkmode = $('#networkmode');
327 /* connected device information */
328 var connectedDeviceArray = [];
329 var devArrayRequested = false;
331 /* Request device list and newtork information on successful connection */
332 socket.on('connect', function () {
333 /* Request device array */
334 if (devArrayRequested === false) {
335 socket.emit('getNwkInfoReq');
336 devArrayRequested = true;
337 }
338 });
340 /* Cloud Info Update */
341 $("#changeBtn").click(function () {
343 var data = {
344 ServiceName: $("#ServiceName").val(),
345 Id: $("#Id").val(),
346 Org: $("#Org").val(),
347 ApiKey: $("#ApiKey").val(),
348 ApiToken: $("#ApiToken").val(),
349 type: $("#type").val(),
350 typeId: $("#typeId").val()
351 };
353 console.log(JSON.stringify(data));
355 socket.emit('setIBMCredentials', data);
356 });
358 /* Handling Newtork open close button */
359 var $allowJoin = $('#allowJoin');
360 var buttonTimer;
361 var joinCnt = false;
363 var buzz_flag = [];
365 /* Initialize network state button */
366 $('.networkstate').hide();
368 /* callback function */
369 function collectorApp_permitJoinButtonCb() {
370 /* did not recieve a confirm to the request */
371 clearInterval(buttonTimer);
373 if ($allowJoin.html() == "opening..") {
374 /* need to retry */
375 $allowJoin.html("open");
376 }
377 else if ($allowJoin.html() == "closing..") {
378 /* need to retry */
379 $allowJoin.html("close");
380 }
381 }
383 /* Handle button press */
384 $allowJoin.click(function () {
385 if ($allowJoin.text() == "open") {
386 /* network is open - lets close */
387 socket.emit('setJoinPermit', { action: "open" });
388 $allowJoin.html("opening..");
389 buttonTimer = setInterval(collectorApp_permitJoinButtonCb, 5000);
390 }
391 else {
392 /* network is closed - lets open */
393 socket.emit('setJoinPermit', { action: "close" });
394 $allowJoin.html("closing..");
395 buttonTimer = setInterval(collectorApp_permitJoinButtonCb, 5000);
396 }
397 });
399 /*********************************************************************
400 * Plotting functions
401 * *******************************************************************/
403 /* Initialize */
404 var networkCanvas = document.getElementById('networkCanvas');
405 var networkCanvasContext = networkCanvas.getContext('2d');
407 /* After getting the device array response plot the devices */
408 function collectorApp_drawNetwork(devArray) {
409 var width = networkCanvas.width;
410 var height = networkCanvas.height;
412 /* erase the canvas */
413 networkCanvasContext.clearRect(0, 0, width, height);
415 /* set canvas x/y to center */
416 networkCanvasContext.translate(width / 2, height / 2);
418 /* variables used for plotting*/
419 var x, y, r, s, angle, i;
421 /* draw central node -- panCoord
422 set up pan-coord parameters */
423 x = 0;
424 y = 0;
425 s = 7;
426 color = "DarkBlue";
427 /* draw concentrator */
428 networkCanvasContext.beginPath();
429 networkCanvasContext.arc(x, y, s, 0, 2 * Math.PI);
430 networkCanvasContext.fillStyle = color;
431 networkCanvasContext.fill();
432 /* select the starting angle for the first node to be 90 */
433 angle = 90;
434 /* calculate the difference in angle between two devices */
435 var diff = 360 / connectedDeviceArray.length;
436 /* draw nodes */
437 for (i = 0; i < connectedDeviceArray.length; i++) {
438 color = "grey";
439 angle = 90 + (i * diff);
441 rssi = connectedDeviceArray[i].rssi;
442 /* set parameters */
443 /* scale RSSI for short range */
444 r = ((height - 80) / 2) * (rssi / -128) + (s * 3);
445 x = r * Math.cos((angle * (Math.PI / 180)));
446 y = r * Math.sin((angle * (Math.PI / 180)));
447 s = 7;
448 /* Draw line to Concentrator (node 0) */
449 networkCanvasContext.setLineDash([5, 2]);
450 networkCanvasContext.beginPath();
451 networkCanvasContext.moveTo(0, 0);
452 networkCanvasContext.lineTo(x, y);
453 networkCanvasContext.strokeStyle = 'black';
454 networkCanvasContext.stroke();
455 /* render the node */
456 networkCanvasContext.beginPath();
457 networkCanvasContext.arc(x, y, s, 0, 2 * Math.PI);
458 networkCanvasContext.fillStyle = color;
459 networkCanvasContext.fill();
460 }
461 /* set canvas x/y back to 0,0 */
462 networkCanvasContext.translate(-(width / 2), -(height / 2));
463 }
465 /*!
466 * @brief Find index of device in the list based on extended
467 * address
468 *
469 * @param extAddr - extended address of the device
470 *
471 * @return index of the device in the connected device list, if present
472 * -1, if not present
473 */
474 function findDeviceIndexExtAddr(extAddr) {
475 /* Check if the device already exists */
476 for (var i = 0; i < connectedDeviceArray.length; i++) {
477 /* check if extended address match */
478 if (connectedDeviceArray[i].ext_addr === extAddr) {
479 return i;
480 }
481 }
482 return -1;
483 }
486 /**********************************************************************
487 Process incoming message from the server
488 ***********************************************************************/
489 /* JSON object coming in for each of the messages below
490 has following elements
491 {
492 active,
493 capabilityInfo,
494 extAddress,
495 humiditysensor,
496 {
497 humidity,
498 temp
499 }
500 lightsensor,
501 {
502 rawData
503 }
504 pollingInterval,
505 reportingInterval,
506 rssi,
507 shortAddress,
508 temperaturesensor,
509 {
510 ambienceTemp,
511 objectTemp
512 }
513 }
514 */
515 function collectorApp_updateNwkInfo(data) {
516 /* clear the curent table entries */
517 $deviceTable.empty();
518 //connectedDeviceArray = JSON.parse(data);
519 if (data) {
520 var index = findDeviceIndexExtAddr(data.ext_addr);
521 if (index !== -1) {
522 connectedDeviceArray[index] = data;
523 } else {
524 //connectedDeviceArray.push(data);
525 console.log("dev not found", data);
526 }
527 }
528 //connectedDeviceArray = data;
529 var len = connectedDeviceArray.length;
530 var count;
532 /* Draw Network */
533 collectorApp_drawNetwork(connectedDeviceArray);
535 for (count = 0; count < len; count++) {
536 var devInfo = connectedDeviceArray[count];
537 var sAddr;
538 var extAddr = "";
539 var capInfo;
540 var sensorS = '<table class="table table-hover table-responsive ">';
541 /* sensor data and rssi is not present when a device
542 info is recieved just after join */
543 var sensorDataFound = 0;
544 var rssi;
546 var date = new Date();
547 var current_hour = date.getHours();
549 if (devInfo.hasOwnProperty('rssi')) {
550 rssi = devInfo.rssi;
551 }
552 else {
553 rssi = "--";
554 }
556 /* Set the values to update */
557 if (devInfo.hasOwnProperty('short_addr')
558 && devInfo.hasOwnProperty('ext_addr')) {
559 /* short address */
560 sAddr = devInfo.short_addr.slice(2);
561 /* Extended address */
562 extAddr = devInfo.ext_addr.slice(2).toString(16);
563 }
564 else {
565 console.log("new device message missing required parameters");
566 continue;
567 }
568 if (devInfo.smart_objects.hasOwnProperty('temperature') && devInfo.smart_objects.temperature.hasOwnProperty(temperature_iid.ambienceTemp)) {
569 sensorDataFound = 1;
570 var value = devInfo.smart_objects.temperature[temperature_iid.ambienceTemp].sensorValue;
571 sensorS += '<tr><td><img src="dist/images/Temperature.png " alt="some_text" height="30" width="30"></td><td>' + value + '°C</td></tr>';
572 }
573 if (devInfo.smart_objects.hasOwnProperty('illuminance') && devInfo.smart_objects.illuminance.hasOwnProperty(illuminance_iid.lightSensor)) {
574 sensorDataFound = 1;
575 var value = devInfo.smart_objects.illuminance[illuminance_iid.lightSensor].sensorValue;
576 sensorS += '<tr><td><img src="dist/images/Light.png " alt="some_text" height="30" width="30"></td><td>' + value + ' lux </td></tr>';
577 }
579 /* Check supported sensors and get the values */
580 if (devInfo.smart_objects.hasOwnProperty('humidity') && devInfo.smart_objects.humidity.hasOwnProperty(humidity_iid.humiditySensor)) {
581 sensorDataFound = 1;
582 var value = devInfo.smart_objects.humidity[humidity_iid.humiditySensor].sensorValue;
583 sensorS += '<tr><td><img src="dist/images/Humidity.png " alt="some_text" height="30" width="30"></td><td>' + value + '% RH</td></tr>';
584 }
586 if (devInfo.smart_objects.hasOwnProperty('barometer') && devInfo.smart_objects.barometer.hasOwnProperty(barometer_iid.pressureSensor)) {
587 sensorDataFound = 1;
588 var value = Math.round(devInfo.smart_objects.barometer[barometer_iid.pressureSensor].sensorValue);
589 sensorS += '<tr><td><img src="dist/images/Pressure.png " alt="some_text" height="30" width="30"></td><td>' + value + ' Pa </td></tr>';
590 }
592 if (devInfo.smart_objects.hasOwnProperty('dIn')) {
593 if (devInfo.smart_objects.dIn.hasOwnProperty(dIn_iid.motion)) {
594 sensorDataFound = 1;
595 if (devInfo.smart_objects.dIn[dIn_iid.motion].dInState) {
596 sensorS += '<tr><td><img src="dist/images/Motion.png" height="30" width="30"></td><td>' + 'Motion Detected' + '</td></tr>';
597 } else {
598 sensorS += '<tr><td><img src="dist/images/No_Motion.png" height="30" width="30"></td><td>' + 'No Motion' + '</td></tr>';
599 }
600 }
601 if (devInfo.smart_objects.dIn.hasOwnProperty(dIn_iid.hallEffectOpen)) {
602 sensorDataFound = 1;
603 if (devInfo.smart_objects.dIn[dIn_iid.hallEffectOpen].dInState) {
604 sensorS += '<tr><td><img src="dist/images/door_open.png" height="30" width="30"></td><td>' + 'Door/Window Open' + '</td></tr>';
605 } else {
606 sensorS += '<tr><td><img src="dist/images/door.png" height="30" width="30"></td><td>' + 'Door/Window Closed' + '</td></tr>';
607 }
608 }
609 if (devInfo.smart_objects.dIn.hasOwnProperty(dIn_iid.hallEffectTampered)) {
610 if (devInfo.smart_objects.dIn[dIn_iid.hallEffectTampered].dInState)
611 console.log("Door/Window sensor on device " + sAddr + "may have been tampered");
612 }
613 if (devInfo.smart_objects.dIn.hasOwnProperty(dIn_iid.doorLock)) {
614 sensorDataFound = 1;
615 if (devInfo.smart_objects.dIn[dIn_iid.doorLock].dInState) {
616 sensorS += '<tr><td><img src="dist/images/Lock.png" height="30" width="30"></td><td>' + 'Door Locked' + '</td></tr>';
617 } else {
618 sensorS += '<tr><td><img src="dist/images/Unlock.png" height="30" width="30"></td><td>' + 'Door Unlocked' + '</td></tr>';
619 }
620 }
621 if (devInfo.smart_objects.dIn.hasOwnProperty(dIn_iid.waterLeak)) {
622 sensorDataFound = 1;
623 if (devInfo.smart_objects.dIn[dIn_iid.waterLeak].dInState) {
624 sensorS += '<tr><td><img src="dist/images/water_leak.png" height="45" width="33"></td><td>' + 'Leak Detected' + '</td></tr>';
625 buzz_flag[parseInt(sAddr)] = 1;
626 } else {
627 sensorS += '<tr><td><img src="dist/images/no_leak.png" height="45" width="33"></td><td>' + 'No Leak' + '</td></tr>';
628 }
629 }
630 }
632 if (devInfo.smart_objects.hasOwnProperty('actuator') && devInfo.smart_objects.actuator.hasOwnProperty(actuator_iid.fan)) {
633 sensorDataFound = 1;
634 var value = devInfo.smart_objects.actuator[actuator_iid.fan].dimmer;
635 sensorS += '<tr><td><img src="dist/images/Fan.png " alt="some_text" height="30" width="30"></td><td>' + value + ' Speed </td></tr>';
636 }
638 if (devInfo.smart_objects.hasOwnProperty('generic') && devInfo.smart_objects.generic.hasOwnProperty(generic_iid.batteryVoltage)) {
639 sensorDataFound = 1;
640 var value = devInfo.smart_objects.generic[generic_iid.batteryVoltage].sensorValue;
641 if (value > 2800) {
642 sensorS += '<tr><td><img src="dist/images/battery_full.png" height="30" width="30"></td><td>' + value + ' mV </td></tr>';
643 }
644 else if (value > 2300) {
645 sensorS += '<tr><td><img src="dist/images/battery_half.png" height="30" width="30"></td><td>' + value + ' mV </td></tr>';
646 }
647 else {
648 sensorS += '<tr><td><img src="dist/images/battery_low.png" height="30" width="30"></td><td>' + value + ' mV </td></tr>';
649 }
651 }
655 if (devInfo.hasOwnProperty('last_reported')) {
656 sensorDataFound = 1;
657 //console.log("Lastreported: ", devInfo.lastreported);
658 sensorS += '<tr><td><img src="dist/images/time.png" height="30" width="30"></td><td>' + devInfo.last_reported + '</td></tr>';
661 }
663 if (sensorDataFound == 0) {
664 sensorS += "--";
665 }
667 sensorS += '</table>';
669 /* add/update device information */
670 if (buzz_flag[parseInt(sAddr)] == 1) {
671 $deviceTable.prepend('<tr><td><table class="table table-responsive"><tr><td>SAddr: 0x' + sAddr.toString(16) + '</td></tr><tr class="ieee"><td>ExAddr: 0x' + extAddr.toString(16).toUpperCase() + '</td></tr><tr><td>RSSI: ' + rssi + ' dBm</td></tr></table></td><td>' + sensorS + '</td>><td>' + "<p button type=button class='test btn btn-default'>Toggle Red LED" + "<div><p button type=button class='buzzerctrl btn btn-default'>Turn Off Buzzer" + "</p></div>" + '</td></tr>');
672 }
673 else {
674 $deviceTable.prepend('<tr><td><table class="table table-responsive"><tr><td>SAddr: 0x' + sAddr.toString(16) + '</td></tr><tr class="ieee"><td>ExAddr: 0x' + extAddr.toString(16).toUpperCase() + '</td></tr><tr><td>RSSI: ' + rssi + ' dBm</td></tr></table></td><td>' + sensorS + '</td>><td>' + "<p button type=button class='test btn btn-default'>Toggle Red LED" + '</td></tr>');
675 }
677 if (devInfo.active == 'true') {
678 /* active device */
679 // TODO Device last updated
680 }
681 else {
682 $('#deviceTable tr:first').fadeTo(5, 0.4);
683 }
684 }
685 }
689 $deviceTable.on("click", "p.test", function () {
690 let data = $(this).closest('tr').find('td:first').text();
691 let n = data.indexOf("ExAddr");
692 let m = data.indexOf("0x");
693 var shortAddr = data.substring((m), (n));
694 socket.emit('deviceActuation', { cmd: "sendToggle", dstAddr: shortAddr });
695 });
697 $deviceTable.on("click", "p.buzzerctrl", function () {
698 let data = $(this).closest('tr').find('td:first').text();
699 let n = data.indexOf("ExAddr");
700 let m = data.indexOf("0x");
701 var shortAddr = data.substring((m), (n));
702 console.log("Sending command to: ", shortAddr);
703 socket.emit('deviceActuation', { cmd: "sendBuzzCtrl", dstAddr: shortAddr });
704 // hide the button after it is pressed, reset the buzzer control flag
705 $(this).hide();
706 buzz_flag[sAddrr_int] = 0;
707 });
709 /* Rcvd network information */
710 socket.on('nwkInfo', function (data) {
711 /* Check if the network is connected */
712 if (!data) {
713 console.log("network is not started yet, we wait for network information");
714 /* Non Hopping Network */
715 $panid.text('--');
716 $coordAddr.text('--');
717 $security.text('--');
718 $networkmode.text("Not Started");
719 /* exit */
720 return false;
721 }
723 //var nwkInfo = JSON.parse(data);
724 var nwkInfo = data;
725 console.log(nwkInfo);
726 $panid.text('0x' + nwkInfo.pan_id.slice(2).toString(16).toUpperCase());
727 $coordAddr.text('0x' + nwkInfo.short_addr.slice(2).toString(16).toUpperCase());
728 $networkmode.text(nwkInfo.mode);
729 if (nwkInfo.security_enabled === 1) {
730 $security.text("Enabled");
731 }
732 else {
733 $security.text("Disabled");
734 }
736 /* Out of box example application does not
737 support opening/closing the network in frequency hopping configuration */
738 if (nwkInfo.mode == "Freq Hopping") {
739 /* Hide the option to open or close the network for new device
740 joins */
741 $("#nwkInformationTable tbody tr.networkstate").hide();
742 }
745 /* Display Network State Information */
746 clearInterval(buttonTimer);
747 if (nwkInfo.state == "started") {
748 $('.networkstate').show();
749 $("#nwkStateText").text("Network close for New Devices");
750 $("#allowJoin").text("open");
751 }
752 else if (nwkInfo.state == "open") {
753 $("#nwkStateText").text("Network open for New Devices");
754 $("#allowJoin").text("close");
755 $('.networkstate').show();
756 if (!joinCnt) {
757 var counter = 60;
758 $('#nwkJoinCountdown').text(counter);
759 joinCnt = setInterval(function () {
760 counter--;
761 if (counter >= 0) {
762 $('#nwkJoinCountdown').text(counter);
763 }
764 if (counter === 0) {
765 clearInterval(joinCnt);
766 joinCnt = false;
767 socket.emit('setJoinPermit', { action: "close" });
768 $allowJoin.html("closing..");
769 $("#allowJoin").text("closing..");
770 $('#nwkJoinCountdown').text("");
771 buttonTimer = setInterval(collectorApp_permitJoinButtonCb, 5000)
772 }
773 }, 1000);
774 }
775 }
776 else if (nwkInfo.state == "close") {
777 $('.networkstate').show();
778 $("#nwkStateText").text("Network close for New Devices");
779 $("#allowJoin").text("open");
780 clearInterval(joinCnt);
781 joinCnt = false;
782 $('#nwkJoinCountdown').text("");
783 }
784 connectedDeviceArray = nwkInfo.devices;
785 collectorApp_updateNwkInfo(null);
786 });
789 /* Rcvd connDevInfoUpdate message */
790 socket.on('connDevInfoUpdate', function (data) {
791 collectorApp_updateNwkInfo(data);
792 });
794 /* close connection */
795 $(window).on('beforeunload', function () {
796 socket.close();
797 });
798 });
799 </script>
800 </body>
802 </html>