/** * JavaScript code for the dashboardV2 logic, refresh and other things * Creation date : 01/02/2020 * Anatole SCHRAMM-HENRY - Th3maz1ng **/ //Dev variables var deviceIPAddr = 'http://192.168.43.46' //Global variables var App = new Object(); var tabInstance = null; var sideNavinstance = null; var modalInstance = null; var connected = true; var setFrequencyReq = null; var setRTCReq = null; var sdCardSizeReq = null; var sdCardActionReq = null; var setIoModeReq = null; var setIoLevelReq = null; //UI elements initialisation document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.sidenav'); var instances = M.Sidenav.init(elems); sideNavinstance = M.Sidenav.getInstance(elems[0]); }); document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.tooltipped'); var instances = M.Tooltip.init(elems); }); document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('select'); var instances = M.FormSelect.init(elems); }); document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.datepicker'); var options = { 'autoClose':true, 'format' : 'd-m-yyyy', 'defaultDate': new Date(), 'setDefaultDate':true, }; var instances = M.Datepicker.init(elems, options); }); document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.timepicker'); var options = { 'twelveHour':false, }; var instances = M.Timepicker.init(elems, options); }); document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.tooltipped'); var options = {}; var instances = M.Tooltip.init(elems, options); }); document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.tabs'); var options = { //'swipeable':true, }; var instances = M.Tabs.init(elems, options); tabInstance = M.Tabs.getInstance(elems[0]); }); document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.modal'); var options = { }; var instances = M.Modal.init(elems, options); modalInstance = M.Modal.getInstance(elems[0]); }); //Dashboard logic initialisation function init() { /*Setting default values and intervals*/ var browserTimeInt = setInterval(() => {browserTime();},1000); let curDate = new Date(); let hours = curDate.getHours() < 10 ? '0'+curDate.getHours() : curDate.getHours(); let minutes = curDate.getMinutes() < 10 ? '0'+curDate.getMinutes() : curDate.getMinutes(); let day = curDate.getDate(); let month = curDate.getMonth()+1; let year = curDate.getFullYear(); elemById('timepicker_id').value = hours+':'+minutes; elemById('datepicker_id').value = day+'-'+month+'-'+year; /*Initializing the App object*/ App.init(); App.registerAutomatedRequest({timeout:5000, pollInterval: 1000, apiEndPoint:deviceIPAddr + '/sab/rtc/get/datetime', gotResponse:(data) => {rtcRefreshHandler(data, 'OK');}, gotError:(e) => {rtcRefreshHandler(e, 'FAIL');}}); App.registerAutomatedRequest({timeout:5000, pollInterval: 10000, apiEndPoint:deviceIPAddr + '/sab/systeminfo', gotResponse:(data) => {sysInfoRefreshHandler(data, 'OK');}, gotError:(e) => {sysInfoRefreshHandler(e, 'FAIL');}}); App.registerAutomatedRequest({timeout:5000, pollInterval: 1000, apiEndPoint:deviceIPAddr + '/sab/wifi/stainfo', gotResponse:(data) => {staInfoRefreshHandler(data, 'OK');}, gotError:(e) => {staInfoRefreshHandler(e, 'FAIL');}}); App.registerAutomatedRequest({timeout:5000, pollInterval: 5000, apiEndPoint:deviceIPAddr + '/sab/io/get/mode', gotResponse:(data) => {ioModeRefreshHandler(data, 'OK');}, gotError:(e) => {ioModeRefreshHandler(e, 'FAIL');}}); App.registerAutomatedRequest({timeout:5000, pollInterval: 1000, apiEndPoint:deviceIPAddr + '/sab/io/get/level', gotResponse:(data) => {ioLevelRefreshHandler(data, 'OK');}, gotError:(e) => {ioLevelRefreshHandler(e, 'FAIL');}}); App.registerAutomatedRequest({timeout:5000, pollInterval: 10000, apiEndPoint:deviceIPAddr + '/sab/power/info', gotResponse:(data) => {powerInfoRefreshHandler(data, 'OK');}, gotError:(e) => {powerInfoRefreshHandler(e, 'FAIL');}}); //All requests needing an UI action: setFrequencyReq = App.buildXMLHttpRequest({timeout:2000, gotResponse:(data) => {setFreqHandler(data, 'OK');}, gotError:(e) => {setFreqHandler(e, 'FAIL');}}); setRTCReq = App.buildXMLHttpRequest({timeout:2000, gotResponse:(data) => {setRTCHandler(data, 'OK');}, gotError:(e) => {setRTCHandler(e, 'FAIL');}}); sdCardSizeReq = App.buildXMLHttpRequest({timeout:2000, gotResponse:(data) => {getCardSizeHandler(data, 'OK');}, gotError:(e) => {getCardSizeHandler(e, 'FAIL');}}); sdCardActionReq = App.buildXMLHttpRequest({timeout:2000, gotResponse:(data) => {CardActionHandler(data, 'OK');}, gotError:(e) => {CardActionHandler(e, 'FAIL');}}); setIoModeReq = App.buildXMLHttpRequest({timeout:2000, gotResponse:(data) => {setIoModeHandler(data, 'OK');}, gotError:(e) => {setIoModeHandler(e, 'FAIL');}}); setIoLevelReq = App.buildXMLHttpRequest({timeout:2000, gotResponse:(data) => {setIoLevelHandler(data, 'OK');}, gotError:(e) => {setIoLevelHandler(e, 'FAIL');}}); scanNetworkReq = App.buildXMLHttpRequest({timeout:2000, gotResponse:(data) => {scanAvailableNetworksHandler(data, 'OK');}, gotError:(e) => {scanAvailableNetworksHandler(data, 'FAIL');}}); } //Callback functions function browserTime() { let curDate = new Date(); let hours = curDate.getHours() < 10 ? '0'+curDate.getHours() : curDate.getHours(); let minutes = curDate.getMinutes() < 10 ? '0'+curDate.getMinutes() : curDate.getMinutes(); let seconds = curDate.getSeconds() < 10 ? '0'+curDate.getSeconds() : curDate.getSeconds(); elemById('browsertime_id').innerHTML = hours+':'+minutes+':'+seconds; } //Helper functions and objects function elemById(id) { return document.getElementById(id); } function rtcRefreshHandler(data,kind) { if(kind !== undefined) { if(kind === 'OK') { let rtcObj = JSON.parse(data); elemById('rtcValue').innerHTML = rtcObj.time + ' ' + rtcObj.date; } else { elemById('rtcValue').innerHTML = 'ERROR'; elemById('execTime').innerHTML = 'NaN'; connected = false; } } } function sysInfoRefreshHandler(data,kind) { if(kind === 'OK') { let systemInfoObj = JSON.parse(data); elemById('temperature').innerHTML = systemInfoObj['temperature'].level + systemInfoObj['temperature'].unit; elemById('ramInfo').innerHTML = systemInfoObj['free RAM']; let cpuFreq = systemInfoObj['CPU freq']; if(cpuFreq == 80) { elemById('cpufreq80_id').checked = true; } else { elemById('cpufreq160_id').checked = true; } elemById('fragInfo').innerHTML = systemInfoObj['heap frag']; elemById('blockInfo').innerHTML = systemInfoObj['max block']; elemById('upTime').innerHTML = systemInfoObj['up time'].days + ' days ' + systemInfoObj['up time'].hours + ' hours ' + systemInfoObj['up time'].minutes + ' minutes ' + systemInfoObj['up time'].seconds + ' seconds '; } else { elemById('temperature').innerHTML = 'NaN'; elemById('ramInfo').innerHTML = 'NaN'; elemById('fragInfo').innerHTML = 'NaN'; elemById('blockInfo').innerHTML = 'NaN'; elemById('upTime').innerHTML = 'NaN'; } } function staInfoRefreshHandler(data,kind) { if(kind === 'OK') { let wifiStaObj = JSON.parse(data); elemById('sigStrength').innerHTML = wifiStaObj.RSSI; elemById('sigStrengthPercent').innerHTML = wifiStaObj.RSSI2; elemById('localIP').innerHTML = wifiStaObj['local IP']; setSigStrenthPicture(wifiStaObj.RSSI2); } else { elemById('sigStrength').innerHTML = 'NaN'; elemById('sigStrengthPercent').innerHTML = 'NaN'; } } //Handler pattern /*function Handler(data,kind) { if(kind === 'OK') { } else { } }*/ function powerInfoRefreshHandler(data,kind) { if(kind === 'OK') { let powerInfo = JSON.parse(data); elemById('battLevel').innerHTML = powerInfo['power type'] == 'USB' ? 'USB' : 'BAT:
' + powerInfoObj.level + '%'; } else { elemById('battLevel').innerHTML = 'NaN'; } } function setIoLevelHandler(data,kind) { if(kind === 'OK') { var ioLevelObj = JSON.parse(data); updateIoLevelImages(ioLevelObj); } else { hideIoLevelImages(); } } function setIoModeHandler(data,kind) { if(kind === 'OK') { var ioModeObj = JSON.parse(data); updateIoModeImages(ioModeObj); } else { hideIoModeImages(); } } function ioLevelRefreshHandler(data,kind) { if(kind === 'OK') { var ioLevelObj = JSON.parse(data); updateIoLevelImages(ioLevelObj); } else { hideIoLevelImages(); } } function ioModeRefreshHandler(data,kind) { if(kind === 'OK') { var ioModeObj = JSON.parse(data); updateIoModeImages(ioModeObj); } else { hideIoModeImages(); } } function CardActionHandler(data,kind) { if(kind === 'OK') { var sdCardObj = JSON.parse(data); if(sdCardObj.status == 'ok') { //Finally we update the card size sdCardSize(); } else { if(elemById('sdcardmounted_id').checked) elemById('sdcardmounted_id').checked = false; else elemById('sdcardmounted_id').checked = true; } } else { } } function setFreqHandler(data,kind) { if(kind === 'OK') { } else { if(elemById('cpufreq80_id').checked) elemById('cpufreq160_id').checked = true; else elemById('cpufreq80_id').checked = true; } } function setRTCHandler(data,kind) { if(kind === 'OK') { } else { } } function getCardSizeHandler(data,kind) { if(kind === 'OK') { var sdCardObj = JSON.parse(data); elemById('cardSize').innerHTML = sdCardObj.size == 0 ? 'NO CARD' : sdCardObj.size + 'GBytes'; elemById('sdcardmounted_id').checked = sdCardObj.size != 0; } else { elemById('cardSize').innerHTML = 'NaN GBytes'; } } function scanAvailableNetworksHandler(data, kind) { if(kind === 'OK') { var networkScanObj = JSON.parse(data); var networksSelect = elemById('networksSelect'); for(var i = 0; i < networksSelect.options.length; i++) { networksSelect.remove(0); } for(var network in networkScanObj) { console.log(network); var opt = document.createElement("option"); opt.text = networkScanObj[network].SSID + '(' + networkScanObj[network].RSSI + ') ' + (networkScanObj[network].Protected === 'Yes' ? 'protected' : 'open'); opt.value = networkScanObj[network].SSID; networksSelect.add(opt); } elems = document.querySelectorAll('select'); instances = M.FormSelect.init(elems); } else { } } //All UI action functions are here function setCpuFrequ(freq) { console.log('cpu frequ : '+freq); setFrequencyReq.open('GET', deviceIPAddr + '/sab/power/set/freq?FREQ='+freq); setFrequencyReq.send(); } function setRtc2BrowserTime() { let d = new Date(); let data = parseInt(d.getDate())+'_'+parseInt(d.getMonth()+1)+'_'+parseInt(d.getFullYear())+'_'+parseInt(d.getHours())+'_'+parseInt(d.getMinutes())+'_'+parseInt(d.getSeconds()+5); console.log(data); setRTCReq.open('GET', deviceIPAddr + '/sab/rtc/set/datetime?datetime='+data); setRTCReq.send(); } function setRtcTime() { let date = elemById('datepicker_id').value; let time = elemById('timepicker_id').value; //We split the date and time : let dtArray = date.split('-'); let tiArray = time.split(':'); let data = parseInt(dtArray[0])+'_'+parseInt(dtArray[1])+'_'+parseInt(dtArray[2])+'_'+parseInt(tiArray[0])+'_'+parseInt(tiArray[1])+'_0'; console.log(data); setRTCReq.open('GET', deviceIPAddr + '/sab/rtc/set/datetime?datetime='+data); setRTCReq.send(); } function sdCardSize() { sdCardSizeReq.open('GET',deviceIPAddr + '/sab/sdcard/size'); sdCardSizeReq.send(); } function mountUnmountCard(id) { if(elemById(id).checked) //We should mount the sd card { sdCardActionReq.open('GET',deviceIPAddr + '/sab/sdcard/action?action=mount'); sdCardActionReq.send(); } else //We unmount it { sdCardActionReq.open('GET',deviceIPAddr + '/sab/sdcard/action?action=unmount'); sdCardActionReq.send(); } } function setIoMode(pin,mode) { var pinOnly = pin.split('_')[0]; setIoModeReq.open('GET',deviceIPAddr + "/sab/io/set/mode?"+pinOnly+'='+ (mode == 'OUTPUT' ? 'OUT' : 'IN')); setIoModeReq.send(); } function setIoLevel(pin,mode) { var pinOnly = pin.split('_')[0]; setIoLevelReq.open('GET',deviceIPAddr + "/sab/io/set/level?"+pinOnly+'='+ (mode == 'HIGH' ? '1' : '0')); setIoLevelReq.send(); } function scanAvailableNetworks() { scanNetworkReq.open('GET', deviceIPAddr + "/sab/wifi/scanner"); scanNetworkReq.send(); } App = { init:function() { if(this.heartBeat == null) //we set the heartBeat only once { console.log("Setting heartbeat"); let heartBeatAjx = this.buildXMLHttpRequest({timeout:2000, apiEndPoint:'/sab/web/apitester', gotResponse:(data) => {console.log('Got heartbeat');connected = true;modalInstance.close();}}); this.heartBeat = setInterval(() => { console.log('connected : '+connected); if(!connected) { console.log('Sending heartbeat'); heartBeatAjx.open('GET', deviceIPAddr + '/sab/web/apitester'); heartBeatAjx.send(); } },5000); } }, onTimeout:function(e) { console.error("Request timed out"); elemById('imgConn').style.display = 'none'; elemById('imgDisco').style.display = 'inline'; setSigStrenthPicture(0); connected = false; modalInstance.open(); }, updateApp:function() { for(i = 0; i < this.requestMap.length; i++) { let reqObj = this.requestMap[i]; reqObj.ajaxObj.open('GET',reqObj.apiEndPoint); reqObj.ajaxObj.send(); } }, onConnected:function() { if(elemById('imgDisco').style.display == 'inline' && elemById('imgConn').style.display == 'none') { console.log("Connected to Swiss Army Board"); elemById('imgDisco').style.display = 'none'; elemById('imgConn').style.display = 'inline'; /*We need to update everything when we connect*/ this.updateApp(); sdCardSize(); } }, registerAutomatedRequest:function(param) { let interval = null; let pollInterval = 1000; //Default to one second if(param === undefined) return interval; if(!('apiEndPoint' in param)) return interval; if('pollInterval' in param) pollInterval = param.pollInterval; let ajax = this.buildXMLHttpRequest(param); interval = setInterval(() => {if(connected){ajax.open('GET', param.apiEndPoint); this.execTimeStart = new Date().getTime(); ajax.send();}},pollInterval); this.intervalMap.push(interval); this.requestMap.push({ajaxObj:ajax, apiEndPoint : param.apiEndPoint}); return interval; }, buildXMLHttpRequest : function(param) { if(param === undefined) return null; let that = this; let ajaxObj = new XMLHttpRequest(); if('timeout' in param) ajaxObj.timeout = param.timeout; else ajaxObj.timeout = 800; ajaxObj.onreadystatechange = function() { switch(this.readyState) { case 0: break; case 1: console.log("Connection established"); break; case 2: console.log("Request received"); break; case 3: console.log("Processing request"); break; case 4: console.log("Response is ready"); if(this.status != 0){that.onConnected(); elemById('execTime').innerHTML = new Date().getTime() - that.execTimeStart;} if(this.status == 200) { console.log("Response : " + this.responseText); if('gotResponse' in param) param.gotResponse(this.responseText); } else { console.log("Error, status is : " + this.status); if('gotError' in param) param.gotError(this.status); } break; default: console.log("Unknown state"); } } if(this.onTimeout !== null) { ajaxObj.ontimeout = this.onTimeout; } return ajaxObj; }, intervalMap:[], requestMap:[], heartBeat:null, execTimeStart:0, }; function showHidePassword(id, action) { if(action === 'show')elemById(id).type = 'text'; else if(action === 'hide')elemById(id).type = 'password'; }; function setSigStrenthPicture(value) { if(value < 5) { elemById('imgSig1').style.display = 'inline'; elemById('imgSig2').style.display = 'none'; elemById('imgSig3').style.display = 'none'; elemById('imgSig4').style.display = 'none'; elemById('imgSig5').style.display = 'none'; } else if(value < 20) { elemById('imgSig1').style.display = 'none'; elemById('imgSig2').style.display = 'inline'; elemById('imgSig3').style.display = 'none'; elemById('imgSig4').style.display = 'none'; elemById('imgSig5').style.display = 'none'; } else if(value < 40) { elemById('imgSig1').style.display = 'none'; elemById('imgSig2').style.display = 'none'; elemById('imgSig3').style.display = 'inline'; elemById('imgSig4').style.display = 'none'; elemById('imgSig5').style.display = 'none'; } else if(value < 80) { elemById('imgSig1').style.display = 'none'; elemById('imgSig2').style.display = 'none'; elemById('imgSig3').style.display = 'none'; elemById('imgSig4').style.display = 'inline'; elemById('imgSig5').style.display = 'none'; } else { elemById('imgSig1').style.display = 'none'; elemById('imgSig2').style.display = 'none'; elemById('imgSig3').style.display = 'none'; elemById('imgSig4').style.display = 'none'; elemById('imgSig5').style.display = 'inline'; } } function updateIoModeImages(obj) { elemById('P0_MODE_I').style.display = obj.P0 == 'IN' ? 'block' : 'none'; elemById('P0_MODE_O').style.display = obj.P0 == 'IN' ? 'none' : 'block'; elemById('P1_MODE_I').style.display = obj.P1 == 'IN' ? 'block' : 'none'; elemById('P1_MODE_O').style.display = obj.P1 == 'IN' ? 'none' : 'block'; elemById('P2_MODE_I').style.display = obj.P2 == 'IN' ? 'block' : 'none'; elemById('P2_MODE_O').style.display = obj.P2 == 'IN' ? 'none' : 'block'; elemById('P3_MODE_I').style.display = obj.P3 == 'IN' ? 'block' : 'none'; elemById('P3_MODE_O').style.display = obj.P3 == 'IN' ? 'none' : 'block'; elemById('P4_MODE_I').style.display = obj.P4 == 'IN' ? 'block' : 'none'; elemById('P4_MODE_O').style.display = obj.P4 == 'IN' ? 'none' : 'block'; elemById('P5_MODE_I').style.display = obj.P5 == 'IN' ? 'block' : 'none'; elemById('P5_MODE_O').style.display = obj.P5 == 'IN' ? 'none' : 'block'; elemById('P6_MODE_I').style.display = obj.P6 == 'IN' ? 'block' : 'none'; elemById('P6_MODE_O').style.display = obj.P6 == 'IN' ? 'none' : 'block'; elemById('P7_MODE_I').style.display = obj.P7 == 'IN' ? 'block' : 'none'; elemById('P7_MODE_O').style.display = obj.P7 == 'IN' ? 'none' : 'block'; } function hideIoModeImages() { elemById('P0_MODE_I').style.display = 'none'; elemById('P0_MODE_O').style.display = 'none'; elemById('P1_MODE_I').style.display = 'none'; elemById('P1_MODE_O').style.display = 'none'; elemById('P2_MODE_I').style.display = 'none'; elemById('P2_MODE_O').style.display = 'none'; elemById('P3_MODE_I').style.display = 'none'; elemById('P3_MODE_O').style.display = 'none'; elemById('P4_MODE_I').style.display = 'none'; elemById('P4_MODE_O').style.display = 'none'; elemById('P5_MODE_I').style.display = 'none'; elemById('P5_MODE_O').style.display = 'none'; elemById('P6_MODE_I').style.display = 'none'; elemById('P6_MODE_O').style.display = 'none'; elemById('P7_MODE_I').style.display = 'none'; elemById('P7_MODE_O').style.display = 'none'; } function updateIoLevelImages(obj) { elemById('P0_LEVEL_H').style.display = obj.P0 == '1' ? 'block' : 'none'; elemById('P0_LEVEL_L').style.display = obj.P0 == '1' ? 'none' : 'block'; elemById('P1_LEVEL_H').style.display = obj.P1 == '1' ? 'block' : 'none'; elemById('P1_LEVEL_L').style.display = obj.P1 == '1' ? 'none' : 'block'; elemById('P2_LEVEL_H').style.display = obj.P2 == '1' ? 'block' : 'none'; elemById('P2_LEVEL_L').style.display = obj.P2 == '1' ? 'none' : 'block'; elemById('P3_LEVEL_H').style.display = obj.P3 == '1' ? 'block' : 'none'; elemById('P3_LEVEL_L').style.display = obj.P3 == '1' ? 'none' : 'block'; elemById('P4_LEVEL_H').style.display = obj.P4 == '1' ? 'block' : 'none'; elemById('P4_LEVEL_L').style.display = obj.P4 == '1' ? 'none' : 'block'; elemById('P5_LEVEL_H').style.display = obj.P5 == '1' ? 'block' : 'none'; elemById('P5_LEVEL_L').style.display = obj.P5 == '1' ? 'none' : 'block'; elemById('P6_LEVEL_H').style.display = obj.P6 == '1' ? 'block' : 'none'; elemById('P6_LEVEL_L').style.display = obj.P6 == '1' ? 'none' : 'block'; elemById('P7_LEVEL_H').style.display = obj.P7 == '1' ? 'block' : 'none'; elemById('P7_LEVEL_L').style.display = obj.P7 == '1' ? 'none' : 'block'; } function hideIoLevelImages() { elemById('P0_LEVEL_H').style.display = 'none'; elemById('P0_LEVEL_L').style.display = 'none'; elemById('P1_LEVEL_H').style.display = 'none'; elemById('P1_LEVEL_L').style.display = 'none'; elemById('P2_LEVEL_H').style.display = 'none'; elemById('P2_LEVEL_L').style.display = 'none'; elemById('P3_LEVEL_H').style.display = 'none'; elemById('P3_LEVEL_L').style.display = 'none'; elemById('P4_LEVEL_H').style.display = 'none'; elemById('P4_LEVEL_L').style.display = 'none'; elemById('P5_LEVEL_H').style.display = 'none'; elemById('P5_LEVEL_L').style.display = 'none'; elemById('P6_LEVEL_H').style.display = 'none'; elemById('P6_LEVEL_L').style.display = 'none'; elemById('P7_LEVEL_H').style.display = 'none'; elemById('P7_LEVEL_L').style.display = 'none'; }