// First, checks if it isn't implemented yet. if (!String.prototype.format) { String.prototype.format = function() { var args = arguments; return this.replace(/{(\d+)}/g, function(match, number) { return typeof args[number] != 'undefined' ? args[number] : match ; }); }; } var nvs_type_t = { NVS_TYPE_U8 : 0x01, /*!< Type uint8_t */ NVS_TYPE_I8 : 0x11, /*!< Type int8_t */ NVS_TYPE_U16 : 0x02, /*!< Type uint16_t */ NVS_TYPE_I16 : 0x12, /*!< Type int16_t */ NVS_TYPE_U32 : 0x04, /*!< Type uint32_t */ NVS_TYPE_I32 : 0x14, /*!< Type int32_t */ NVS_TYPE_U64 : 0x08, /*!< Type uint64_t */ NVS_TYPE_I64 : 0x18, /*!< Type int64_t */ NVS_TYPE_STR : 0x21, /*!< Type string */ NVS_TYPE_BLOB : 0x42, /*!< Type blob */ NVS_TYPE_ANY : 0xff /*!< Must be last */ } ; var task_state_t = { 0 : "eRunning", /*!< A task is querying the state of itself, so must be running. */ 1 : "eReady", /*!< The task being queried is in a read or pending ready list. */ 2 : "eBlocked", /*!< The task being queried is in the Blocked state. */ 3 : "eSuspended", /*!< The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ 4 : "eDeleted" } var releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases'; var recovery = false; var enableAPTimer = true; var enableStatusTimer = true; var commandHeader = 'squeezelite -b 500:2000 -d all=info '; var pname, ver, otapct, otadsc; var blockAjax = false; var blockFlashButton = false; var apList = null; var selectedSSID = ""; var refreshAPInterval = null; var checkStatusInterval = null; var StatusIntervalActive = false; var RefreshAPIIntervalActive = false; var LastRecoveryState=null; var output = ''; function stopCheckStatusInterval(){ if(checkStatusInterval != null){ clearTimeout(checkStatusInterval); checkStatusInterval = null; } StatusIntervalActive = false; } function stopRefreshAPInterval(){ if(refreshAPInterval != null){ clearTimeout(refreshAPInterval); refreshAPInterval = null; } RefreshAPIIntervalActive = false; } function startCheckStatusInterval(){ StatusIntervalActive = true; checkStatusInterval = setTimeout(checkStatus, 3000); } function startRefreshAPInterval(){ RefreshAPIIntervalActive = true; refreshAPInterval = setTimeout(refreshAP(false), 4500); // leave enough time for the initial scan } function RepeatCheckStatusInterval(){ if(StatusIntervalActive) startCheckStatusInterval(); } function RepeatRefreshAPInterval(){ if(RefreshAPIIntervalActive) startRefreshAPInterval(); } $(document).ready(function(){ $("#wifi-status").on("click", ".ape", function() { $( "#wifi" ).slideUp( "fast", function() {}); $( "#connect-details" ).slideDown( "fast", function() {}); }); $("#manual_add").on("click", ".ape", function() { selectedSSID = $(this).text(); $( "#ssid-pwd" ).text(selectedSSID); $( "#wifi" ).slideUp( "fast", function() {}); $( "#connect_manual" ).slideDown( "fast", function() {}); $( "#connect" ).slideUp( "fast", function() {}); //update wait screen $( "#loading" ).show(); $( "#connect-success" ).hide(); $( "#connect-fail" ).hide(); }); $("#wifi-list").on("click", ".ape", function() { selectedSSID = $(this).text(); $( "#ssid-pwd" ).text(selectedSSID); $( "#wifi" ).slideUp( "fast", function() {}); $( "#connect_manual" ).slideUp( "fast", function() {}); $( "#connect" ).slideDown( "fast", function() {}); //update wait screen $( "#loading" ).show(); $( "#connect-success" ).hide(); $( "#connect-fail" ).hide(); }); $("#cancel").on("click", function() { selectedSSID = ""; $( "#connect" ).slideUp( "fast", function() {}); $( "#connect_manual" ).slideUp( "fast", function() {}); $( "#wifi" ).slideDown( "fast", function() {}); }); $("#manual_cancel").on("click", function() { selectedSSID = ""; $( "#connect" ).slideUp( "fast", function() {}); $( "#connect_manual" ).slideUp( "fast", function() {}); $( "#wifi" ).slideDown( "fast", function() {}); }); $("#join").on("click", function() { performConnect(); }); $("#manual_join").on("click", function() { performConnect($(this).data('connect')); }); $("#ok-details").on("click", function() { $( "#connect-details" ).slideUp( "fast", function() {}); $( "#wifi" ).slideDown( "fast", function() {}); }); $("#ok-credits").on("click", function() { $( "#credits" ).slideUp( "fast", function() {}); $( "#app" ).slideDown( "fast", function() {}); }); $("#acredits").on("click", function(event) { event.preventDefault(); $( "#app" ).slideUp( "fast", function() {}); $( "#credits" ).slideDown( "fast", function() {}); }); $("#ok-connect").on("click", function() { $( "#connect-wait" ).slideUp( "fast", function() {}); $( "#wifi" ).slideDown( "fast", function() {}); }); $("#disconnect").on("click", function() { $( "#connect-details-wrap" ).addClass('blur'); $( "#diag-disconnect" ).slideDown( "fast", function() {}); }); $("#no-disconnect").on("click", function() { $( "#diag-disconnect" ).slideUp( "fast", function() {}); $( "#connect-details-wrap" ).removeClass('blur'); }); $("#yes-disconnect").on("click", function() { stopCheckStatusInterval(); selectedSSID = ""; $( "#diag-disconnect" ).slideUp( "fast", function() {}); $( "#connect-details-wrap" ).removeClass('blur'); $.ajax({ url: '/connect.json', dataType: 'text', method: 'DELETE', cache: false, contentType: 'application/json; charset=utf-8', data: JSON.stringify({ 'timestamp': Date.now()}) }); startCheckStatusInterval(); $( "#connect-details" ).slideUp( "fast", function() {}); $( "#wifi" ).slideDown( "fast", function() {}) }); $("input#show-nvs").on("click", function() { this.checked=this.checked?1:0; if(this.checked){ $('a[href^="#tab-nvs"]').show(); } else { $('a[href^="#tab-nvs"]').hide(); } }); $("input#autoexec-cb").on("click", function() { var data = { 'timestamp': Date.now() }; autoexec = (this.checked)?1:0; data['config'] = {}; data['config'] = { autoexec : { value : autoexec, type : 33 } } showMessage('please wait for the ESP32 to reboot', 'MESSAGING_WARNING'); $.ajax({ url: '/config.json', dataType: 'text', method: 'POST', cache: false, // headers: { "X-Custom-autoexec": autoexec }, contentType: 'application/json; charset=utf-8', data: JSON.stringify(data), error: function (xhr, ajaxOptions, thrownError) { console.log(xhr.status); console.log(thrownError); if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR'); }, complete: function(response) { //var returnedResponse = JSON.parse(response.responseText); console.log(response.responseText); console.log('sent config JSON with headers:', autoexec); console.log('now triggering reboot'); $.ajax({ url: '/reboot_ota.json', dataType: 'text', method: 'POST', cache: false, contentType: 'application/json; charset=utf-8', data: JSON.stringify({ 'timestamp': Date.now()}), error: function (xhr, ajaxOptions, thrownError) { console.log(xhr.status); console.log(thrownError); if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR'); }, complete: function(response) { console.log('reboot call completed'); } }); } }); }); $("input#save-autoexec1").on("click", function() { var data = { 'timestamp': Date.now() }; autoexec1 = $("#autoexec1").val(); data['config'] = {}; data['config'] = { autoexec1 : { value : autoexec1, type : 33 } } $.ajax({ url: '/config.json', dataType: 'text', method: 'POST', cache: false, // headers: { "X-Custom-autoexec1": autoexec1 }, contentType: 'application/json; charset=utf-8', data: JSON.stringify(data), error: function (xhr, ajaxOptions, thrownError) { console.log(xhr.status); console.log(thrownError); if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR'); } }); console.log('sent config JSON with headers:', autoexec1); console.log('sent data:', JSON.stringify(data)); }); $("input#save-gpio").on("click", function() { var data = { 'timestamp': Date.now() }; var config = {}; var headers = {}; $("input.gpio").each(function() { var id = $(this)[0].id; var pin = $(this).val(); if (pin != '') { config[id] = {}; config[id].value = pin; config[id].type = nvs_type_t.NVS_TYPE_STR; } }); data['config'] = config; $.ajax({ url: '/config.json', dataType: 'text', method: 'POST', cache: false, headers: headers, contentType: 'application/json; charset=utf-8', data: JSON.stringify(data), error: function (xhr, ajaxOptions, thrownError) { console.log(xhr.status); console.log(thrownError); if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR'); } }); console.log('sent config JSON with headers:', JSON.stringify(headers)); console.log('sent config JSON with data:', JSON.stringify(data)); }); $("#save-nvs").on("click", function() { var headers = {}; var data = { 'timestamp': Date.now() }; var config = {}; $("input.nvs").each(function() { var key = $(this)[0].id; var val = $(this).val(); var nvs_type = parseInt($(this)[0].attributes.nvs_type.nodeValue,10); if (key != '') { config[key] = {}; if(nvs_type == nvs_type_t.NVS_TYPE_U8 || nvs_type == nvs_type_t.NVS_TYPE_I8 || nvs_type == nvs_type_t.NVS_TYPE_U16 || nvs_type == nvs_type_t.NVS_TYPE_I16 || nvs_type == nvs_type_t.NVS_TYPE_U32 || nvs_type == nvs_type_t.NVS_TYPE_I32 || nvs_type == nvs_type_t.NVS_TYPE_U64 || nvs_type == nvs_type_t.NVS_TYPE_I64) { config[key].value = parseInt(val); } else { config[key].value = val; } config[key].type = nvs_type; } }); var key = $("#nvs-new-key").val(); var val = $("#nvs-new-value").val(); if (key != '') { // headers["X-Custom-" +key] = val; config[key] = {}; config[key].value = val; config[key].type = 33; } data['config'] = config; $.ajax({ url: '/config.json', dataType: 'text', method: 'POST', cache: false, headers: headers, contentType: 'application/json; charset=utf-8', data : JSON.stringify(data), error: function (xhr, ajaxOptions, thrownError) { console.log(xhr.status); console.log(thrownError); if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR'); } }); console.log('sent config JSON with headers:', JSON.stringify(headers)); console.log('sent config JSON with data:', JSON.stringify(data)); }); $("#fwUpload").on("click", function() { var upload_path = "/flash.json"; var fileInput = document.getElementById("flashfilename").files; if (fileInput.length == 0) { alert("No file selected!"); } else { var file = fileInput[0]; var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (xhttp.readyState == 4) { if (xhttp.status == 200) { showMessage(xhttp.responseText, 'MESSAGING_INFO') } else if (xhttp.status == 0) { showMessage("Upload connection was closed abruptly!", 'MESSAGING_ERROR'); } else { showMessage(xhttp.status + " Error!\n" + xhttp.responseText, 'MESSAGING_ERROR'); } } }; xhttp.open("POST", upload_path, true); xhttp.send(file); } enableStatusTimer = true; }); $("#flash").on("click", function() { var data = { 'timestamp': Date.now() }; if (blockFlashButton) return; blockFlashButton = true; var url = $("#fwurl").val(); data['config'] = { fwurl : { value : url, type : 33 } }; $.ajax({ url: '/config.json', dataType: 'text', method: 'POST', cache: false, contentType: 'application/json; charset=utf-8', data: JSON.stringify(data), error: function (xhr, ajaxOptions, thrownError) { console.log(xhr.status); console.log(thrownError); if (thrownError != '') showMessage(thrownError, 'MESSAGING_ERROR'); } }); enableStatusTimer = true; }); $("#generate-command").on("click", function() { var commandLine = commandHeader + '-n "' + $("#player").val() + '"'; if (output == 'bt') { commandLine += ' -o "BT -n \'' + $("#btsink").val() + '\'" -R -Z 192000'; } else if (output == 'spdif') { commandLine += ' -o SPDIF -R -Z 192000'; } else { commandLine += ' -o I2S'; } if ($("#optional").val() != '') { commandLine += ' ' + $("#optional").val(); } $("#autoexec1").val(commandLine); }); $('[name=audio]').on("click", function(){ if (this.id == 'bt') { $("#btsinkdiv").show(200); output = 'bt'; } else if (this.id == 'spdif') { $("#btsinkdiv").hide(200); output = 'spdif'; } else { $("#btsinkdiv").hide(200); output = 'i2s'; } }); $('#fwcheck').on("click", function(){ $("#releaseTable").html(""); $.getJSON(releaseURL, function(data) { var i=0; data.forEach(function(release) { var url = ''; release.assets.forEach(function(asset) { if (asset.name.match(/\.bin$/)) { url = asset.browser_download_url; } }); var [ver, idf, cfg, branch] = release.name.split('#'); var body = release.body; body = body.replace(/\'/ig, "\""); body = body.replace(/[\s\S]+(### Revision Log[\s\S]+)### ESP-IDF Version Used[\s\S]+/, "$1"); body = body.replace(/- \(.+?\) /g, "- "); var [date, time] = release.created_at.split('T'); var trclass = (i++ > 6)?' hide':''; $("#releaseTable").append( "