123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- <html>
- <head>
- <meta name="apple-mobile-web-app-capable" content="yes" />
- <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
- <meta charset="UTF-8">
- <title>ArozOS IoT Hub</title>
- <link rel="stylesheet" href="../../../script/semantic/semantic.min.css">
- <link rel="manifest" href="manifest.json">
- <script src="../../../script/jquery.min.js"></script>
- <script src="../../../script/semantic/semantic.min.js"></script>
- <script src="../../../script/ao_module.js"></script>
- <style>
- .ultrasmall.image{
- height:35px;
- margin:0px !important;
- margin-right:10px !important;
- }
- .selectable{
- cursor:pointer;
- }
- .selectable:hover{
- background-color:#f0f0f0;
-
- }
- .noborder{
- border: 1px solid transparent !important;
- }
- .controlBtn{
- position:absolute;
- right:8px;
- bottom:8px;
- }
- .devIcon{
- border-radius: 10px;
- }
- .primary.button{
- background-color: #4aa9eb !important;
- }
- .bottom.item{
- position:absolute;
- bottom: 0px;
- left:0px;
- width:100%;
- font-size:80%;
- }
- #sideMenu{
- height: calc(100% - 85px);
- }
- .primary.button{
- background-color: #4287f5 !important;
- }
- body{
- height:100%;
- background:rgba(247,247,247,0.95);
- }
- .popupInterface{
- height:80%;
- width:95%;
- overflow-y:auto;
- }
- </style>
- </head>
- <body>
- <div id="sidemenu" class="ui right vertical menu sidebar">
- <div class="item">
- <div class="ui header">
- ArozOS IoT Hub
- <div class="sub header">Universal IoT Controller</div>
- </div>
- </div>
- <a class="selectable item" onClick="loadDevList();hideSideMenu();">
- <i class="refresh icon"></i> Refresh List
- </a>
- <a class="selectable item" onClick="scanDevices();hideSideMenu();">
- <i class="search icon"></i> Scan Devices
- </a>
- <div class="bottom item">
- CopyRight ArozOS Project 2020 - <span class="thisYear"></span>
- </div>
- </div>
- <div class="pusher">
- <div class="ui menu">
- <a class="item noborder" href="index.html"><img class="ui ultrasmall circular image" src="img/menu_icon.svg"> IoT Hub</a>
- <a class="right item" onClick="toggleSideMenu();"><i class="content icon"></i></a>
- </div>
- <div id="devList" class="ui container">
- <div class="ui basic segment HDSDev">
- <div class="ui grid">
- <div class="four wide column"><img class="ui tiny devIcon image" src="img/system/loading.gif"></div>
- <div class="twelve wide column">
- <div class="ui container">
- <div class="ui header">
- <span class="devHeader">Scanning</span>
- <div class="sub devProperty header">IoT Hub take a while to scan your network for the first startup.</div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <br><br><br>
- </div>
- <!-- Show more information about thsi device-->
- <div id="moreInfoInterface" class="ui active dimmer" style="display:none;">
- <div style="position:absolute;width:100%;height:100%;left:0px;top:0px;" onClick='$("#moreInfoInterface").fadeOut("fast");'>
- </div>
- <div id="informationItnerface" class="ui segment mainUI popupInterface" style="text-align: left;">
- <div class="ui header">
- Device Properties
- </div>
- <br>
- <div class="ui horizontal form">
- <div class="field">
- <label>Device UUID</label>
- <input id="duid" type="text" readonly="true">
- </div>
- <div class="field">
- <label>IP Address</label>
- <input id="ipaddr" type="text" readonly="true">
- </div>
- <div class="field">
- <label>Communication Port</label>
- <input id="comport" type="text" readonly="true">
- </div>
- <div class="field">
- <label>Manufacturer</label>
- <input id="manufacturer" type="text" readonly="true">
- </div>
- <div class="field">
- <label>Version</label>
- <input id="version" type="text" readonly="true">
- </div>
- </div>
- <br>
- <button class="ui primary button" onClick='$("#moreInfoInterface").fadeOut("fast");'>Close</button>
- <br><br>
- </div>
- </div>
- <!-- Editing can be done on this device -->
- <div id="editInterface" class="ui active dimmer" style="display:none;">
- <div style="position:absolute;width:100%;height:100%;left:0px;top:0px;" onClick='$("#editInterface").fadeOut("fast");'>
- </div>
- <div class="ui segment mainUI popupInterface" >
- <div class="ui header">
- Edit Device Records
- </div>
- <p>Set Device Nickname</p>
- <div class="ui action fluid small input">
- <input class="deviceNickname" type="text" uuid="" placeholder="New Nickname" autocomplete="off">
- <button class="ui positive button" onclick="setNickName(this)">Update</button>
- </div>
- <div class="ui inverted positive segment nicnameSetConfirm" style="display:none;">
- <p><i class="checkmark icon"></i> Device Nickname Updated</p>
- </div>
- <div class="ui divider"></div>
- <br>
- <button class="ui primary button" onClick='$("#editInterface").fadeOut("fast");'>Close</button>
- <br><br>
- </div>
- </div>
- <!-- Action can be done on this device -->
- <div id="actioninterface" class="ui active dimmer" style="display:none;">
- <div style="position:absolute;width:100%;height:100%;left:0px;top:0px;" onClick='$("#actioninterface").fadeOut("fast");'>
- </div>
- <div id="informationItnerface" class="ui segment mainUI popupInterface" style="text-align: left;">
- <div class="ui header">
- Device Actions
- </div>
- <br>
- <div class="ui form" id="statusList">
- <h3><i class="ui loading spinner icon"></i> Loading</h3>
- </div>
- <div class="ui divider"></div>
- <div class="ui horizontal form" id="actionForm">
- </div>
- <br>
- <button class="ui primary button" onClick='$("#actioninterface").fadeOut("fast");'>Close</button>
- <br><br>
- </div>
- </div>
- <div id="loadingMask" class="ui active dimmer" style="display:none;">
- <div class="ui text loader">Scanning in Progress</div>
- </div>
- <script>
- var currentlyViewingDevices = "";
- var uselocal = false; //Use Local as command sender or use Host as command sender
- var username = $("#data_session_username").text().trim();
- //ao_module Float Window functions
- ao_module_setWindowTitle("IoT Hub");
- ao_module_setWindowSize(465,730,true);
- if (!ao_module_virtualDesktop){
- $("body").css("background-color","white");
- }
- //Initiate the page content
- loadDevList();
-
- function inputbox(message, placeholder = ""){
- var input = prompt(message, placeholder);
- if (input != null) {
- return input;
- }else{
- return false;
- }
- }
- function scanDevices(){
- $("#loadingMask").show();
- $.get("../../../system/iot/scan", function(data){
- loadDevList();
- $("#loadingMask").hide();
- });
- }
- function hideSideMenu(){
- $('.right.sidebar').sidebar('hide');
- }
- function showMore(object){
- var device = $(object).parent().parent();
- var duid = device.attr("uuid");
- var lastseen = device.attr("devip");
- var deviceData = device.attr("devicedata");
- deviceData = JSON.parse(decodeURIComponent(deviceData))
- console.log(deviceData);
- $("#duid").val(duid);
- $("#ipaddr").val(lastseen);
- $("#comport").val(deviceData.Port);
- $("#manufacturer").val(deviceData.Manufacturer);
- $("#version").val(deviceData.Version);
- currentlyViewingDevices = duid;
- $("#moreInfoInterface").fadeIn('fast');
- }
- function loadDevList(){
- $.get("../../../system/iot/list", function(data){
- $("#devList").html("");
- if (data.error !== undefined){
- alert(data.error);
- }else{
- data.forEach(device => {
- var deviceData = encodeURIComponent(JSON.stringify(device));
- $("#devList").append(`<div class="ui segment HDSDev" devicedata="${deviceData}" uuid="${device.DeviceUUID}" devIp="${device.IPAddr}" port="${device.Port}" location="local">
- <div class="ui grid">
- <div class="four wide column"><img class="ui tiny devIcon image" src="../../../system/iot/icon?devid=${device.DeviceUUID}"></div>
- <div class="twelve wide column">
- <div class="ui container">
- <div class="ui header">
- <span class="devHeader">${device.Name}</span>
- <div class="sub devProperty header">${device.Model}</div>
- </div>
- </div>
- </div>
- </div>
- <div class="controlBtn infoMount">
- <button class="ui icon button" title="Edit Device Nickname" onClick="edit(this);"><i class="edit icon"></i></button>
- <button class="ui icon button" title="Show More" onClick="showMore(this);"><i class="info circle icon"></i></button>
- <button class="ui primary icon button" title="Actions" onClick="action(this);"><i class="options icon"></i></button>
- </div>
- </div>`);
- });
- if (data.length == 0){
- //No device found
- $("#devList").html(`<div class="ui basic segment HDSDev">
- <div class="ui grid">
- <div class="four wide column"><img class="ui tiny devIcon image" src="img/system/not-found.svg"></div>
- <div class="twelve wide column">
- <div class="ui container">
- <div class="ui header">
- <span class="devHeader">No Device Found</span>
- <div class="sub devProperty header">Want to create your own IoT devices with ESP8266 & Arduino IDE? <br>Check out the <a href="https://github.com/tobychui/Home-Dynamic" target="_blank">HomeDynamic</a> System!</div>
- </div>
- </div>
- </div>
- </div>
- </div>`);
- }
- //Load the nickname of each device if it exists
- $(".HDSDev").each(function(){
- //Get iui nickname
- var devUUID = $(this).attr("uuid");
- var targetDOMElement = $(this);
- $.ajax({
- url: "../../../system/iot/nickname",
- data: {opr: "get", uuid: devUUID},
- success: function(data){
- if (data.error == undefined){
- //No error. Render it to the header
- var currentHeader = $(targetDOMElement).find(".devHeader").text();
- var newHeader = data + " (" + currentHeader + ") ";
- $(targetDOMElement).find(".devHeader").text(newHeader);
- }
- }
- });
- })
-
- }
- });
- }
- function toggleSideMenu(){
- $("#sidemenu").sidebar('toggle');
- }
- function setNickName(input){
- var inputValue = $(input).parent().find(".deviceNickname").val();
- var devUUID = $(input).parent().find(".deviceNickname").attr("uuid");
- if (inputValue !== ""){
- //Set the new value
- $.ajax({
- url: "../../../system/iot/nickname",
- data: {opr: "set", uuid: devUUID, name: inputValue},
- success: function(data){
- if (data.error !== undefined){
- alert(data.error);
- }else{
- //OK!
- $("#editInterface").find(".nicnameSetConfirm").slideDown("fast").delay(3000).slideUp("fast");
- //Update the device list
- loadDevList();
- }
- }
- });
- }
- }
- function edit(object){
- //get the device UUID
- var devdata = $(object).parent().parent().attr("devicedata");
- devdata = JSON.parse(decodeURIComponent(devdata));
- var devUUID = devdata.DeviceUUID;
- $("#editInterface").find(".deviceNickname").attr("uuid",devUUID);
- //Get the device nickname from server side
- $.ajax({
- url: "../../../system/iot/nickname",
- data: {opr: "get", uuid: devUUID},
- success: function(data){
- if (data.error !== undefined){
- //Nickname not set yet.
- $("#editInterface").find(".deviceNickname").val("");
- }else{
- $("#editInterface").find(".deviceNickname").val(data);
- }
- }
- })
- //Show the interface
- $("#editInterface").fadeIn('fast');
- }
- function executeEndpoint(object, targetValue=""){
- var deviceID = $(object).attr("devid");
- var epd = JSON.parse(decodeURIComponent($(object).attr("epd")));
- if (epd.Type == "integer" || epd.Type == "float"){
- //Check if it is in range
- if (epd.Max && targetValue > epd.Max ){
- //Snap to max value if over max
- targetValue = epd.Max;
- }
- if (epd.Min && targetValue < epd.Min){
- //Snap to min value if under min
- targetValue = epd.Min;
- }
- }else if (epd.Type == "string"){
- //Check if regex
- if (epd.Regex && targetValue.match(stringToRegex(epd.Regex)) == null){
- //Invalid string input. Reject operation
- alert("Input string does not match request regex structure: " + epd.Regex);
- return;
- }
- }
- //Request the backend to activate the endpoint
- console.log(deviceID, epd, targetValue);
- $.ajax({
- url: "../../../system/iot/execute",
- data: {devid: deviceID, eptname: epd.Name, payload: targetValue},
- success: function(data){
- if (data.error !== undefined){
- alert(data.error);
- }else{
- //OK. Reload status
- updateStatus(deviceID);
- }
- }
- })
- }
- const stringToRegex = str => {
- // Main regex
- const main = str.match(/\/(.+)\/.*/)[1]
-
- // Regex options
- const options = str.match(/\/.+\/(.*)/)[1]
-
- // Compiled regex
- return new RegExp(main, options)
- }
- function action(object){
- //Clear the action form
- $("#actionForm").html("");
- //Generate the list of endpoinui from the device data
- var device = $(object).parent().parent();
- var deviceData = device.attr("devicedata");
- deviceData = JSON.parse(decodeURIComponent(deviceData));
- var epts = deviceData.ControlEndpoints;
- if (epts == null || typeof(epts) == undefined || epts.length == 0 ){
- //This device has no control endpoints. Show status info only.
- updateStatus(deviceData.DeviceUUID);
- }else{
- epts.forEach(ept => {
- //Check which type of ept is this. Accept {string, integer, float, bool, none}
- var encodedEptData = encodeURIComponent(JSON.stringify(ept));
- var deviceID = deviceData.DeviceUUID;
- var name = ept.Name;
- if (ept.Type == "string"){
- $("#actionForm").append(`<div name="${ept.Name}" devid="${deviceID}" epd="${encodedEptData}" class="field">
- <label>${ept.Desc}</label>
- <div class="ui action input">
- <input type="text" placeholder="${name}">
- <button class="ui primary icon button" title="Send" onclick="executeEndpoint(this.parentNode.parentNode, this.parentNode.parentNode.getElementsByTagName('input')[0].value)"><i class="send icon"></i></button>
- </div>
- </div>`);
- }else if (ept.Type == "integer"){
- var min = "";
- var max = "";
- if (ept.Min != undefined){
- min = ept.Min;
- }
- if (ept.Max != undefined){
- max = ept.Max;
- }
- $("#actionForm").append(`<div name="${ept.Name}" devid="${deviceID}" epd="${encodedEptData}" class="field">
- <label>${ept.Desc}</label>
- <div class="ui action input">
- <input type="number" min="${min}" max="${max}" placeholder="${name}">
- <button class="ui primary icon button" title="Send" onclick="executeEndpoint(this.parentNode.parentNode, this.parentNode.parentNode.getElementsByTagName('input')[0].value)"><i class="send icon"></i></button>
- </div>
- </div>`);
- }else if (ept.Type == "float"){
- var min = "";
- var max = "";
- var step = "0.1";
- if (ept.Min != undefined){
- min = ept.Min;
- }
- if (ept.Max != undefined){
- max = ept.Max;
- }
- if (ept.Steps != undefined){
- step = ept.Steps;
- }
- $("#actionForm").append(`<div name="${ept.Name}" devid="${deviceID}" epd="${encodedEptData}" class="field">
- <label>${ept.Desc}</label>
- <div class="ui action input">
- <input type="number" min="${min}" max="${max}" step="${step}" placeholder="${name}">
- <button class="ui primary icon button" onclick="executeEndpoint(this.parentNode.parentNode, this.parentNode.parentNode.getElementsByTagName('input')[0].value)" title="Send"><i class="send icon"></i></button>
- </div>
- </div>`);
- }else if (ept.Type == "bool"){
- $("#actionForm").append(`<div name="${ept.Name}" devid="${deviceID}" epd="${encodedEptData}" class="field">
- <div class="ui toggle checkbox">
- <input type="checkbox" id="${encodeURIComponent(ept.Name)}" onchange="executeEndpoint(this.parentNode.parentNode, this.checked);">
- <label for="${encodeURIComponent(ept.Name)}">${ept.Name}</label>
- </div></div>`);
-
- }else if (ept.Type == "none"){
- //No action. (aka just a GET request endpoint)
- $("#actionForm").append(`<div devid="${deviceID}" epd="${encodedEptData}" class="field">
- <button class="ui info fluid button" title="${ept.Desc}" onclick="executeEndpoint(this.parentNode);">${name}</button>
- </div>`);
- }
- });
- updateStatus(deviceData.DeviceUUID);
- }
- console.log(deviceData);
- $("#actioninterface").fadeIn('fast');
- }
- function updateStatus(deviceUUID){
- //Get iui status
- $.ajax({
- url: "../../../system/iot/status",
- data: {devid: deviceUUID},
- success: function(data){
- //Look for fields that have the same name. If not, append it to status field
- if (data.error !== undefined){
- $("#statusList").html(`<h3>Connection Lost</h3><br><p>${data.error}</p>`);
- }else{
- //OK! Append it
- $("#statusList").html("");
- for (var key in data) {
- var found = false;
- $("#actionForm").find(".field").each(function(){
- var thisName = $(this).attr("name");
- if (thisName == key){
- //Set iui value
- var targetInput = $(this).find("input");
- if (targetInput.attr('type') == "checkbox"){
- //For handling checkbox
- if (data[key] == true){
- targetInput[0].checked = true;
- }else{
- targetInput[0].checked = false;
- }
- }else{
- //For handling other input fields
- $(this).find("input").val(data[key]);
- }
-
- found = true;
- }
- });
- if (found == false){
- //Append to status field
- $("#statusList").append(`<div class="ui header">
- ${data[key]}
- <div class="sub header">${key}</div>
- </div>`);
- }
- }
- }
- }
- })
- }
- function updateIframeSize(){
- $("#controlUI").attr("width",$("#actionMainUI").width());
- $("#controlUI").attr("height",$("#actionMainUI").height());
- $("#controlUI").css("width",$("#actionMainUI").width());
- $("#controlUI").css("height",$("#actionMainUI").height());
- }
- $(window).on("resize",function(){
- updateIframeSize();
- });
- $(".thisYear").text(new Date().getFullYear());
- </script>
- </body>
- </html>
|