var he = require('he');
var Promise = require('es6-promise').Promise;
window.bootstrap = require('bootstrap');
import Cookies from 'js-cookie';
if (!String.prototype.format) {
Object.assign(String.prototype, {
format() {
const args = arguments;
return this.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] !== 'undefined' ? args[number] : match;
});
},
});
}
if (!String.prototype.encodeHTML) {
Object.assign(String.prototype, {
encodeHTML() {
return he.encode(this).replace(/\n/g, '
');
},
});
}
Object.assign(Date.prototype, {
toLocalShort() {
const opt = { dateStyle: 'short', timeStyle: 'short' };
return this.toLocaleString(undefined, opt);
},
});
function handleNVSVisible(){
let nvs_previous_checked = isEnabled(Cookies.get("show-nvs"));
$('input#show-nvs')[0].checked = nvs_previous_checked ;
if ($('input#show-nvs')[0].checked || recovery) {
$('*[href*="-nvs"]').show();
} else {
$('*[href*="-nvs"]').hide();
}
}
function isEnabled(val) {
return val!=undefined && typeof val === 'string' && val.match("[Yy1]");
}
const nvsTypes = {
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 */,
};
const btIcons = {
bt_playing: {'label':'','icon': 'media_bluetooth_on'},
bt_disconnected: {'label':'','icon': 'media_bluetooth_off'},
bt_neutral: {'label':'','icon': 'bluetooth'},
bt_connecting: {'label':'','icon': 'bluetooth_searching'},
bt_connected: {'label':'','icon': 'bluetooth_connected'},
bt_disabled: {'label':'','icon': 'bluetooth_disabled'},
play_arrow: {'label':'','icon': 'play_circle_filled'},
pause: {'label':'','icon': 'pause_circle'},
stop: {'label':'','icon': 'stop_circle'},
'': {'label':'','icon':''}
};
const batIcons = [
{ icon: "battery_0_bar", label:'▪', ranges: [{ f: 5.8, t: 6.8 }, { f: 8.8, t: 10.2 }] },
{ icon: "battery_2_bar", label:'▪▪', ranges: [{ f: 6.8, t: 7.4 }, { f: 10.2, t: 11.1 }] },
{ icon: "battery_3_bar", label:'▪▪▪', ranges: [{ f: 7.4, t: 7.5 }, { f: 11.1, t: 11.25 }] },
{ icon: "battery_4_bar", label:'▪▪▪▪', ranges: [{ f: 7.5, t: 7.8 }, { f: 11.25, t: 11.7 }] }
];
const btStateIcons = [
{ desc: 'Idle', sub: ['bt_neutral'] },
{ desc: 'Discovering', sub: ['bt_connecting'] },
{ desc: 'Discovered', sub: ['bt_connecting'] },
{ desc: 'Unconnected', sub: ['bt_disconnected'] },
{ desc: 'Connecting', sub: ['bt_connecting'] },
{
desc: 'Connected',
sub: ['bt_connected', 'play_arrow', 'bt_playing', 'pause', 'stop'],
},
{ desc: 'Disconnecting', sub: ['bt_disconnected'] },
];
const pillcolors = {
MESSAGING_INFO: 'badge-success',
MESSAGING_WARNING: 'badge-warning',
MESSAGING_ERROR: 'badge-danger',
};
const connectReturnCode = {
OK: 0,
FAIL: 1,
DISC: 2,
LOST: 3,
RESTORE: 4,
ETH: 5
}
const taskStates = {
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',
};
let flashState = {
NONE: 0,
REBOOT_TO_RECOVERY: 2,
SET_FWURL: 5,
FLASHING: 6,
DONE: 7,
UPLOADING: 8,
ERROR: 9,
UPLOADCOMPLETE: 10,
_state: -1,
olderRecovery: false,
statusText: '',
flashURL: '',
flashFileName: '',
statusPercent: 0,
Completed: false,
recovery: false,
prevRecovery: false,
updateModal: new bootstrap.Modal(document.getElementById('otadiv'), {}),
reset: function () {
this.olderRecovery = false;
this.statusText = '';
this.statusPercent = -1;
this.flashURL = '';
this.flashFileName = undefined;
this.UpdateProgress();
$('#rTable tr.release').removeClass('table-success table-warning');
$('.flact').prop('disabled', false);
$('#flashfilename').value = null;
$('#fw-url-input').value = null;
if(!this.isStateError()){
$('span#flash-status').html('');
$('#fwProgressLabel').parent().removeClass('bg-danger');
}
this._state = this.NONE
return this;
},
isStateUploadComplete: function () {
return this._state == this.UPLOADCOMPLETE;
},
isStateError: function () {
return this._state == this.ERROR;
},
isStateNone: function () {
return this._state == this.NONE;
},
isStateRebootRecovery: function () {
return this._state == this.REBOOT_TO_RECOVERY;
},
isStateSetUrl: function () {
return this._state == this.SET_FWURL;
},
isStateFlashing: function () {
return this._state == this.FLASHING;
},
isStateDone: function () {
return this._state == this.DONE;
},
isStateUploading: function () {
return this._state == this.UPLOADING;
},
init: function () {
this._state = this.NONE;
return this;
},
SetStateError: function () {
this._state = this.ERROR;
$('#fwProgressLabel').parent().addClass('bg-danger');
return this;
},
SetStateNone: function () {
this._state = this.NONE;
return this;
},
SetStateRebootRecovery: function () {
this._state = this.REBOOT_TO_RECOVERY;
// Reboot system to recovery mode
this.SetStatusText('Starting recovery mode.')
$.ajax({
url: '/recovery.json',
context: this,
dataType: 'text',
method: 'POST',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
timestamp: Date.now(),
}),
error: function (xhr, _ajaxOptions, thrownError) {
this.setOTAError(`Unexpected error while trying to restart to recovery. (status=${xhr.status ?? ''}, error=${thrownError ?? ''} ) `);
},
complete: function (response) {
this.SetStatusText('Waiting for system to boot.')
},
});
return this;
},
SetStateSetUrl: function () {
this._state = this.SET_FWURL;
this.statusText = 'Sending firmware download location.';
let confData = {
fwurl: {
value: this.flashURL,
type: 33,
}
};
post_config(confData);
return this;
},
SetStateFlashing: function () {
this._state = this.FLASHING;
return this;
},
SetStateDone: function () {
this._state = this.DONE;
this.reset();
return this;
},
SetStateUploading: function () {
this._state = this.UPLOADING;
return this.SetStatusText('Sending file to device.');
},
SetStateUploadComplete: function () {
this._state = this.UPLOADCOMPLETE;
return this;
},
isFlashExecuting: function () {
return true === (this._state != this.UPLOADING && (this.statusText !== '' || this.statusPercent >= 0));
},
toString: function () {
let keys = Object.keys(this);
return keys.find(x => this[x] === this._state);
},
setOTATargets: function () {
this.flashURL = '';
this.flashFileName = '';
this.flashURL = $('#fw-url-input').val();
let fileInput = $('#flashfilename')[0].files;
if (fileInput.length > 0) {
this.flashFileName = fileInput[0];
}
if (this.flashFileName.length == 0 && this.flashURL.length == 0) {
this.setOTAError('Invalid url or file. Cannot start OTA');
}
return this;
},
setOTAError: function (message) {
this.SetStateError().SetStatusPercent(0).SetStatusText(message).reset();
return this;
},
ShowDialog: function () {
if (!this.isStateNone()) {
this.updateModal.show();
$('.flact').prop('disabled', true);
}
return this;
},
SetStatusPercent: function (pct) {
var pctChanged = (this.statusPercent != pct);
this.statusPercent = pct;
if (pctChanged) {
if (!this.isStateUploading() && !this.isStateFlashing()) {
this.SetStateFlashing();
}
if (pct == 100) {
if (this.isStateFlashing()) {
this.SetStateDone();
}
else if (this.isStateUploading()) {
this.statusPercent = 0;
this.SetStateFlashing();
}
}
this.UpdateProgress().ShowDialog();
}
return this;
},
SetStatusText: function (txt) {
var changed = (this.statusText != txt);
this.statusText = txt;
if (changed) {
$('span#flash-status').html(this.statusText);
this.ShowDialog();
}
return this;
},
UpdateProgress: function () {
$('.progress-bar')
.css('width', this.statusPercent + '%')
.attr('aria-valuenow', this.statusPercent)
.text(this.statusPercent + '%')
$('.progress-bar').html((this.isStateDone() ? 100 : this.statusPercent) + '%');
return this;
},
StartOTA: function () {
this.logEvent(this.StartOTA.name);
$('#fwProgressLabel').parent().removeClass('bg-danger');
this.setOTATargets();
if (this.isStateError()) {
return this;
}
if (!recovery) {
this.SetStateRebootRecovery();
}
else {
this.SetStateFlashing().TargetReadyStartOTA();
}
return this;
},
UploadLocalFile: function () {
this.SetStateUploading();
const xhttp = new XMLHttpRequest();
xhttp.context = this;
var boundHandleUploadProgressEvent = this.HandleUploadProgressEvent.bind(this);
var boundsetOTAError=this.setOTAError.bind(this);
xhttp.upload.addEventListener("progress",boundHandleUploadProgressEvent, false);
xhttp.onreadystatechange = function () {
if (xhttp.readyState === 4) {
if (xhttp.status === 0 || xhttp.status === 404) {
boundsetOTAError(`Upload Failed. Recovery version might not support uploading. Please use web update instead.`);
}
}
};
xhttp.open('POST', '/flash.json', true);
xhttp.send(this.flashFileName);
},
TargetReadyStartOTA: function () {
if (recovery && this.prevRecovery && !this.isStateRebootRecovery() && !this.isStateFlashing()) {
// this should only execute once, while being in a valid state
return this;
}
this.logEvent(this.TargetReadyStartOTA.name);
if (!recovery) {
console.error('Event TargetReadyStartOTA fired in the wrong mode ');
return this;
}
this.prevRecovery = true;
if (this.flashFileName !== '') {
this.UploadLocalFile();
}
else if (this.flashURL != '') {
this.SetStateSetUrl();
}
else {
this.setOTAError('Invalid URL or file name while trying to start the OTa process')
}
},
HandleUploadProgressEvent: function (data) {
this.logEvent(this.HandleUploadProgressEvent.name);
this.SetStateUploading().SetStatusPercent(Math.round(data.loaded / data.total * 100)).SetStatusText('Uploading file to device');
},
EventTargetStatus: function (data) {
if (!this.isStateNone()) {
this.logEvent(this.EventTargetStatus.name);
}
if (data.ota_pct ?? -1 >= 0) {
this.olderRecovery = true;
this.SetStatusPercent(data.ota_pct);
}
if ((data.ota_dsc ?? '') != '') {
this.olderRecovery = true;
this.SetStatusText(data.ota_dsc);
}
if (data.recovery != undefined) {
this.recovery = data.recovery === 1 ? true : false;
}
if (this.isStateRebootRecovery() && this.recovery) {
this.TargetReadyStartOTA();
}
},
EventOTAMessageClass: function (data) {
this.logEvent(this.EventOTAMessageClass.name);
var otaData = JSON.parse(data);
this.SetStatusPercent(otaData.ota_pct).SetStatusText(otaData.ota_dsc);
},
logEvent: function (fun) {
console.log(`${fun}, flash state ${this.toString()}, recovery: ${this.recovery}, ota pct: ${this.statusPercent}, ota desc: ${this.statusText}`);
}
};
window.hideSurrounding = function (obj) {
$(obj).parent().parent().hide();
}
let presetsloaded = false;
let is_i2c_locked = false;
let statusInterval = 2000;
let messageInterval = 2500;
function post_config(data) {
let confPayload = {
timestamp: Date.now(),
config: data
};
$.ajax({
url: '/config.json',
dataType: 'text',
method: 'POST',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(confPayload),
error: handleExceptionResponse,
});
}
window.hFlash = function () {
// reset file upload selection if any;
$('#flashfilename').value = null
flashState.StartOTA();
}
window.handleReboot = function (link) {
if (link == 'reboot_ota') {
$('#reboot_ota_nav').removeClass('active').prop("disabled", true); delayReboot(500, '', 'reboot_ota');
}
else {
$('#reboot_nav').removeClass('active'); delayReboot(500, '', link);
}
}
function isConnected(){
return ConnectedTo.ip && ConnectedTo.ip!='0.0.0.0';
}
function getIcon(icons){
return isConnected()?icons.icon:icons.label;
}
function handlebtstate(data) {
let icon = '';
let tt = '';
if (data.bt_status !== undefined && data.bt_sub_status !== undefined) {
const iconindex = btStateIcons[data.bt_status].sub[data.bt_sub_status];
if (iconindex) {
icon = btIcons[iconindex];
tt = btStateIcons[data.bt_status].desc;
} else {
icon = btIcons.bt_connected;
tt = 'Output status';
}
}
$('#o_type').attr('title', tt);
$('#o_bt').html(isConnected()?icon.label:icon.text);
}
function handleTemplateTypeRadio(outtype) {
$('#o_type').children('span').css({ display: 'none' });
if (outtype === 'bt') {
output = 'bt';
} else if (outtype === 'spdif') {
output = 'spdif';
} else {
output = 'i2s';
}
$('#' + output).prop('checked', true);
$('#o_' + output).css({ display: 'inline' });
}
function handleExceptionResponse(xhr, _ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(thrownError);
if (thrownError !== '') {
showLocalMessage(thrownError, 'MESSAGING_ERROR');
}
}
function HideCmdMessage(cmdname) {
$('#toast_' + cmdname)
.removeClass('table-success')
.removeClass('table-warning')
.removeClass('table-danger')
.addClass('table-success')
.removeClass('show');
$('#msg_' + cmdname).html('');
}
function showCmdMessage(cmdname, msgtype, msgtext, append = false) {
let color = 'table-success';
if (msgtype === 'MESSAGING_WARNING') {
color = 'table-warning';
} else if (msgtype === 'MESSAGING_ERROR') {
color = 'table-danger';
}
$('#toast_' + cmdname)
.removeClass('table-success')
.removeClass('table-warning')
.removeClass('table-danger')
.addClass(color)
.addClass('show');
let escapedtext = msgtext
.substring(0, msgtext.length - 1)
.encodeHTML()
.replace(/\n/g, '
');
escapedtext =
($('#msg_' + cmdname).html().length > 0 && append
? $('#msg_' + cmdname).html() + '
'
: '') + escapedtext;
$('#msg_' + cmdname).html(escapedtext);
}
let releaseURL =
'https://api.github.com/repos/sle118/squeezelite-esp32/releases';
let recovery = false;
let messagesHeld = false;
const commandHeader = 'squeezelite -b 500:2000 -d all=info -C 30 -W';
//let blockFlashButton = false;
let apList = null;
//let selectedSSID = '';
//let checkStatusInterval = null;
let messagecount = 0;
let messageseverity = 'MESSAGING_INFO';
let SystemConfig = {};
let LastCommandsState = null;
var output = '';
let hostName = '';
let versionName = 'Squeezelite-ESP32';
let prevmessage = '';
let project_name = versionName;
let board_model = '';
let platform_name = versionName;
let preset_name = '';
let btSinkNamesOptSel = '#cfg-audio-bt_source-sink_name';
let ConnectedTo = {};
let ConnectingToSSID = {};
let lmsBaseUrl;
let prevLMSIP = '';
const ConnectingToActions = {
'CONN': 0, 'MAN': 1, 'STS': 2,
}
Promise.prototype.delay = function (duration) {
return this.then(
function (value) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(value);
}, duration);
});
},
function (reason) {
return new Promise(function (_resolve, reject) {
setTimeout(function () {
reject(reason);
}, duration);
});
}
);
};
function getConfigJson(slimMode) {
const config = {};
$('input.nvs').each(function (_index, entry) {
if (!slimMode) {
const nvsType = parseInt(entry.attributes.nvs_type.value, 10);
if (entry.id !== '') {
config[entry.id] = {};
if (
nvsType === nvsTypes.NVS_TYPE_U8 ||
nvsType === nvsTypes.NVS_TYPE_I8 ||
nvsType === nvsTypes.NVS_TYPE_U16 ||
nvsType === nvsTypes.NVS_TYPE_I16 ||
nvsType === nvsTypes.NVS_TYPE_U32 ||
nvsType === nvsTypes.NVS_TYPE_I32 ||
nvsType === nvsTypes.NVS_TYPE_U64 ||
nvsType === nvsTypes.NVS_TYPE_I64
) {
config[entry.id].value = parseInt(entry.value);
} else {
config[entry.id].value = entry.value;
}
config[entry.id].type = nvsType;
}
} else {
config[entry.id] = entry.value;
}
});
const key = $('#nvs-new-key').val();
const val = $('#nvs-new-value').val();
if (key !== '') {
if (!slimMode) {
config[key] = {};
config[key].value = val;
config[key].type = 33;
} else {
config[key] = val;
}
}
return config;
}
function handleHWPreset(allfields, reboot) {
const selJson = JSON.parse(allfields[0].value);
var cmd = allfields[0].attributes.cmdname.value;
console.log(`selected model: ${selJson.name}`);
let confPayload = {
timestamp: Date.now(),
config: { model_config: { value: selJson.name, type: 33 } }
};
for (const [name, value] of Object.entries(selJson.config)) {
const storedval = (typeof value === 'string' || value instanceof String) ? value : JSON.stringify(value);
confPayload.config[name] = {
value: storedval,
type: 33,
}
showCmdMessage(
cmd,
'MESSAGING_INFO',
`Setting ${name}=${storedval} `,
true
);
}
showCmdMessage(
cmd,
'MESSAGING_INFO',
`Committing `,
true
);
$.ajax({
url: '/config.json',
dataType: 'text',
method: 'POST',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(confPayload),
error: function (xhr, _ajaxOptions, thrownError) {
handleExceptionResponse(xhr, _ajaxOptions, thrownError);
showCmdMessage(
cmd,
'MESSAGING_ERROR',
`Unexpected error ${(thrownError !== '') ? thrownError : 'with return status = ' + xhr.status} `,
true
);
},
success: function (response) {
showCmdMessage(
cmd,
'MESSAGING_INFO',
`Saving complete `,
true
);
console.log(response);
if (reboot) {
delayReboot(2500, cmd);
}
},
});
}
// pull json file from https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/b462691f69e2ad31ac95c547af6ec97afb0f53db/squeezelite-esp32-presets.json and
function loadPresets() {
if ($("#cfg-hw-preset-model_config").length == 0) return;
if (presetsloaded) return;
presetsloaded = true;
$('#cfg-hw-preset-model_config').html('');
$.getJSON(
'https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/',
{ _: new Date().getTime() },
function (data) {
$.each(data, function (key, val) {
$('#cfg-hw-preset-model_config').append(``);
if (preset_name !== '' && preset_name == val.name) {
$('#cfg-hw-preset-model_config').val(preset_name);
}
});
if (preset_name !== '') {
('#prev_preset').show().val(preset_name);
}
}
).fail(function (jqxhr, textStatus, error) {
const err = textStatus + ', ' + error;
console.log('Request Failed: ' + err);
}
);
}
function delayReboot(duration, cmdname, ota = 'reboot') {
const url = '/' + ota + '.json';
$('tbody#tasks').empty();
$('#tasks_sect').css('visibility', 'collapse');
Promise.resolve({ cmdname: cmdname, url: url })
.delay(duration)
.then(function (data) {
if (data.cmdname.length > 0) {
showCmdMessage(
data.cmdname,
'MESSAGING_WARNING',
'System is rebooting.\n',
true
);
} else {
showLocalMessage('System is rebooting.\n', 'MESSAGING_WARNING');
}
console.log('now triggering reboot');
$("button[onclick*='handleReboot']").addClass('rebooting');
$.ajax({
url: data.url,
dataType: 'text',
method: 'POST',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
timestamp: Date.now(),
}),
error: handleExceptionResponse,
complete: function () {
console.log('reboot call completed');
Promise.resolve(data)
.delay(6000)
.then(function (rdata) {
if (rdata.cmdname.length > 0) {
HideCmdMessage(rdata.cmdname);
}
getCommands();
getConfig();
});
},
});
});
}
// eslint-disable-next-line no-unused-vars
window.saveAutoexec1 = function (apply) {
showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Saving.\n', false);
let commandLine = commandHeader + ' -n "' + $('#player').val() + '"';
if (output === 'bt') {
commandLine += ' -o "BT" -R -Z 192000';
showCmdMessage(
'cfg-audio-tmpl',
'MESSAGING_INFO',
'Remember to configure the Bluetooth audio device name.\n',
true
);
} else if (output === 'spdif') {
commandLine += ' -o SPDIF -Z 192000';
} else {
commandLine += ' -o I2S';
}
if ($('#optional').val() !== '') {
commandLine += ' ' + $('#optional').val();
}
const data = {
timestamp: Date.now(),
};
data.config = {
autoexec1: { value: commandLine, type: 33 },
autoexec: {
value: $('#disable-squeezelite').prop('checked') ? '0' : '1',
type: 33,
},
};
$.ajax({
url: '/config.json',
dataType: 'text',
method: 'POST',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data),
error: handleExceptionResponse,
complete: function (response) {
if (
response.responseText &&
JSON.parse(response.responseText).result === 'OK'
) {
showCmdMessage('cfg-audio-tmpl', 'MESSAGING_INFO', 'Done.\n', true);
if (apply) {
delayReboot(1500, 'cfg-audio-tmpl');
}
} else if (JSON.parse(response.responseText).result) {
showCmdMessage(
'cfg-audio-tmpl',
'MESSAGING_WARNING',
JSON.parse(response.responseText).Result + '\n',
true
);
} else {
showCmdMessage(
'cfg-audio-tmpl',
'MESSAGING_ERROR',
response.statusText + '\n'
);
}
console.log(response.responseText);
},
});
console.log('sent data:', JSON.stringify(data));
}
window.handleDisconnect = function () {
$.ajax({
url: '/connect.json',
dataType: 'text',
method: 'DELETE',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
timestamp: Date.now(),
}),
});
}
function setPlatformFilter(val) {
if ($('.upf').filter(function () { return $(this).text().toUpperCase() === val.toUpperCase() }).length > 0) {
$('#splf').val(val).trigger('input');
return true;
}
return false;
}
window.handleConnect = function () {
ConnectingToSSID.ssid = $('#manual_ssid').val();
ConnectingToSSID.pwd = $('#manual_pwd').val();
ConnectingToSSID.dhcpname = $('#dhcp-name2').val();
$("*[class*='connecting']").hide();
$('#ssid-wait').text(ConnectingToSSID.ssid);
$('.connecting').show();
$.ajax({
url: '/connect.json',
dataType: 'text',
method: 'POST',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
timestamp: Date.now(),
ssid: ConnectingToSSID.ssid,
pwd: ConnectingToSSID.pwd
}),
error: handleExceptionResponse,
});
// now we can re-set the intervals regardless of result
}
$(document).ready(function () {
$('.material-icons').each(function (_index, entry) {
entry.attributes['icon']=entry.textContent;
});
setIcons(true);
handleNVSVisible();
flashState.init();
$('#fw-url-input').on('input', function () {
if ($(this).val().length > 8 && ($(this).val().startsWith('http://') || $(this).val().startsWith('https://'))) {
$('#start-flash').show();
}
else {
$('#start-flash').hide();
}
});
$('.upSrch').on('input', function () {
const val = this.value;
$("#rTable tr").removeClass(this.id + '_hide');
if (val.length > 0) {
$(`#rTable td:nth-child(${$(this).parent().index() + 1})`).filter(function () {
return !$(this).text().toUpperCase().includes(val.toUpperCase());
}).parent().addClass(this.id + '_hide');
}
$('[class*="_hide"]').hide();
$('#rTable tr').not('[class*="_hide"]').show()
});
setTimeout(refreshAP, 1500);
$('#WifiConnectDialog')[0].addEventListener('shown.bs.modal', function (event) {
$("*[class*='connecting']").hide();
if (event?.relatedTarget) {
ConnectingToSSID.Action = ConnectingToActions.CONN;
if ($(event.relatedTarget).children('td:eq(1)').text() == ConnectedTo.ssid) {
ConnectingToSSID.Action = ConnectingToActions.STS;
}
else {
if (!$(event.relatedTarget).is(':last-child')) {
ConnectingToSSID.ssid = $(event.relatedTarget).children('td:eq(1)').text();
$('#manual_ssid').val(ConnectingToSSID.ssid);
}
else {
ConnectingToSSID.Action = ConnectingToActions.MAN;
ConnectingToSSID.ssid = '';
$('#manual_ssid').val(ConnectingToSSID.ssid);
}
}
}
if (ConnectingToSSID.Action !== ConnectingToActions.STS) {
$('.connecting-init').show();
$('#manual_ssid').trigger('focus');
}
else {
handleWifiDialog();
}
});
$('#WifiConnectDialog')[0].addEventListener('hidden.bs.modal', function () {
$('#WifiConnectDialog input').val('');
});
$('#uCnfrm')[0].addEventListener('shown.bs.modal', function () {
$('#selectedFWURL').text($('#fw-url-input').val());
});
$('input#show-commands')[0].checked = LastCommandsState === 1;
$('a[href^="#tab-commands"]').hide();
$('#load-nvs').on('click', function () {
$('#nvsfilename').trigger('click');
});
$('#nvsfilename').on('change', function () {
if (typeof window.FileReader !== 'function') {
throw "The file API isn't supported on this browser.";
}
if (!this.files) {
throw 'This browser does not support the `files` property of the file input.';
}
if (!this.files[0]) {
return undefined;
}
const file = this.files[0];
let fr = new FileReader();
fr.onload = function (e) {
let data = {};
try {
data = JSON.parse(e.target.result);
} catch (ex) {
alert('Parsing failed!\r\n ' + ex);
}
$('input.nvs').each(function (_index, entry) {
$(this).parent().removeClass('bg-warning').removeClass('bg-success');
if (data[entry.id]) {
if (data[entry.id] !== entry.value) {
console.log(
'Changed ' + entry.id + ' ' + entry.value + '==>' + data[entry.id]
);
$(this).parent().addClass('bg-warning');
$(this).val(data[entry.id]);
}
else {
$(this).parent().addClass('bg-success');
}
}
});
var changed = $("input.nvs").children('.bg-warning');
if (changed) {
alert('Highlighted values were changed. Press Commit to change on the device');
}
}
fr.readAsText(file);
this.value = null;
}
);
$('#clear-syslog').on('click', function () {
messagecount = 0;
messageseverity = 'MESSAGING_INFO';
$('#msgcnt').text('');
$('#syslogTable').html('');
});
$('#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 () { });
});
$('input#show-commands').on('click', function () {
this.checked = this.checked ? 1 : 0;
if (this.checked) {
$('a[href^="#tab-commands"]').show();
LastCommandsState = 1;
} else {
LastCommandsState = 0;
$('a[href^="#tab-commands"]').hide();
}
});
$('input#show-nvs').on('click', function () {
this.checked = this.checked ? 1 : 0;
Cookies.set("show-nvs", this.checked?'Y':'N');
handleNVSVisible();
});
$('#btn_reboot_recovery').on('click', function () {
handleReboot('recovery');
});
$('#btn_reboot').on('click', function () {
handleReboot('reboot');
});
$('#btn_flash').on('click', function () {
hFlash();
});
$('#save-autoexec1').on('click', function () {
saveAutoexec1(false);
});
$('#commit-autoexec1').on('click', function () {
saveAutoexec1(true);
});
$('#btn_disconnect').on('click', function () {
ConnectedTo={};
refreshAPHTML2();
$.ajax({
url: '/connect.json',
dataType: 'text',
method: 'DELETE',
cache: false,
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
timestamp: Date.now(),
}),
});
});
$('#btnJoin').on('click', function () {
handleConnect();
});
$('#reboot_nav').on('click', function () {
handleReboot('reboot');
});
$('#reboot_ota_nav').on('click', function () {
handleReboot('reboot_ota');
});
$('#save-as-nvs').on('click', function () {
const config = getConfigJson(true);
const a = document.createElement('a');
a.href = URL.createObjectURL(
new Blob([JSON.stringify(config, null, 2)], {
type: 'text/plain',
})
);
a.setAttribute(
'download',
'nvs_config_' + hostName + '_' + Date.now() + 'json'
);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
$('#save-nvs').on('click', function () {
post_config(getConfigJson(false));
});
$('#fwUpload').on('click', function () {
const fileInput = document.getElementById('flashfilename').files;
if (fileInput.length === 0) {
alert('No file selected!');
} else {
$('#fw-url-input').value = null;
flashState.StartOTA();
}
});
$('[name=output-tmpl]').on('click', function () {
handleTemplateTypeRadio(this.id);
});
$('#chkUpdates').on('click', function () {
$('#rTable').html('');
$.getJSON(releaseURL, function (data) {
let i = 0;
const branches = [];
data.forEach(function (release) {
const namecomponents = release.name.split('#');
const branch = namecomponents[3];
if (!branches.includes(branch)) {
branches.push(branch);
}
});
let fwb = '';
branches.forEach(function (branch) {
fwb += '';
});
$('#fwbranch').append(fwb);
data.forEach(function (release) {
let url = '';
release.assets.forEach(function (asset) {
if (asset.name.match(/\.bin$/)) {
url = asset.browser_download_url;
}
});
const namecomponents = release.name.split('#');
const ver = namecomponents[0];
const cfg = namecomponents[2];
const branch = namecomponents[3];
var bits = ver.substr(ver.lastIndexOf('-') + 1);
bits = (bits == '32' || bits == '16') ? bits : '';
let body = release.body;
body = body.replace(/'/gi, '"');
body = body.replace(
/[\s\S]+(### Revision Log[\s\S]+)### ESP-IDF Version Used[\s\S]+/,
'$1'
);
body = body.replace(/- \(.+?\) /g, '- ').encodeHTML();
$('#rTable').append(`