1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140 |
- 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, '<br />');
- },
- });
- }
- 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, '<br />');
- escapedtext =
- ($('#msg_' + cmdname).html().length > 0 && append
- ? $('#msg_' + cmdname).html() + '<br/>'
- : '') + 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('<option>--</option>');
- $.getJSON(
- 'https://gist.githubusercontent.com/sle118/dae585e157b733a639c12dc70f0910c5/raw/',
- { _: new Date().getTime() },
- function (data) {
- $.each(data, function (key, val) {
- $('#cfg-hw-preset-model_config').append(`<option value='${JSON.stringify(val).replace(/"/g, '\"').replace(/\'/g, '\"')}'>${val.name}</option>`);
- 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 += '<option value="' + branch + '">' + branch + '</option>';
- });
- $('#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(`<tr class='release ' fwurl='${url}'>
- <td data-bs-toggle='tooltip' title='${body}'>${ver}</td><td>${new Date(release.created_at).toLocalShort()}
- </td><td class='upf'>${cfg}</td><td>${branch}</td><td>${bits}</td></tr>`
- );
- });
- if (i > 7) {
- $('#releaseTable').append(
- "<tr id='showall'>" +
- "<td colspan='6'>" +
- "<input type='button' id='showallbutton' class='btn btn-info' value='Show older releases' />" +
- '</td>' +
- '</tr>'
- );
- $('#showallbutton').on('click', function () {
- $('tr.hide').removeClass('hide');
- $('tr#showall').addClass('hide');
- });
- }
- $('#searchfw').css('display', 'inline');
- if (!setPlatformFilter(platform_name)) {
- setPlatformFilter(project_name)
- }
- $('#rTable tr.release').on('click', function () {
- var url = this.attributes['fwurl'].value;
- if (lmsBaseUrl) {
- url = url.replace(/.*\/download\//, lmsBaseUrl + '/plugins/SqueezeESP32/firmware/');
- }
- $('#fw-url-input').val(url);
- $('#start-flash').show();
- $('#rTable tr.release').removeClass('table-success table-warning');
- $(this).addClass('table-success table-warning');
- });
- }).fail(function () {
- alert('failed to fetch release history!');
- });
- });
- $('#fwcheck').on('click', function () {
- $('#releaseTable').html('');
- $('#fwbranch').empty();
- $.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 += '<option value="' + branch + '">' + branch + '</option>';
- });
- $('#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 idf = namecomponents[1];
- const cfg = namecomponents[2];
- const branch = namecomponents[3];
- 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, '- ');
- const trclass = i++ > 6 ? ' hide' : '';
- $('#releaseTable').append(
- "<tr class='release" +
- trclass +
- "'>" +
- "<td data-bs-toggle='tooltip' title='" +
- body +
- "'>" +
- ver +
- '</td>' +
- '<td>' +
- new Date(release.created_at).toLocalShort() +
- '</td>' +
- '<td>' +
- cfg +
- '</td>' +
- '<td>' +
- idf +
- '</td>' +
- '<td>' +
- branch +
- '</td>' +
- "<td><input type='button' class='btn btn-success' value='Select' data-bs-url='" +
- url +
- "' onclick='setURL(this);' /></td>" +
- '</tr>'
- );
- });
- if (i > 7) {
- $('#releaseTable').append(
- "<tr id='showall'>" +
- "<td colspan='6'>" +
- "<input type='button' id='showallbutton' class='btn btn-info' value='Show older releases' />" +
- '</td>' +
- '</tr>'
- );
- $('#showallbutton').on('click', function () {
- $('tr.hide').removeClass('hide');
- $('tr#showall').addClass('hide');
- });
- }
- $('#searchfw').css('display', 'inline');
- }).fail(function () {
- alert('failed to fetch release history!');
- });
- });
- $('#updateAP').on('click', function () {
- refreshAP();
- console.log('refresh AP');
- });
- // first time the page loads: attempt to get the connection status and start the wifi scan
- getConfig();
- getCommands();
- getMessages();
- checkStatus();
- });
- // eslint-disable-next-line no-unused-vars
- window.setURL = function (button) {
- let url = button.dataset.url;
- $('[data-bs-url^="http"]')
- .addClass('btn-success')
- .removeClass('btn-danger');
- $('[data-bs-url="' + url + '"]')
- .addClass('btn-danger')
- .removeClass('btn-success');
- // if user can proxy download through LMS, modify the URL
- if (lmsBaseUrl) {
- url = url.replace(/.*\/download\//, lmsBaseUrl + '/plugins/SqueezeESP32/firmware/');
- }
- $('#fwurl').val(url);
- }
- function rssiToIcon(rssi) {
- if (rssi >= -55) {
- return {'label':'****','icon':`signal_wifi_statusbar_4_bar`};
- } else if (rssi >= -60) {
- return {'label':'***','icon':`network_wifi_3_bar`};
- } else if (rssi >= -65) {
- return {'label':'**','icon':`network_wifi_2_bar`};
- } else if (rssi >= -70) {
- return {'label':'*','icon':`network_wifi_1_bar`};
- } else {
- return {'label':'.','icon':`signal_wifi_statusbar_null`};
- }
- }
- function refreshAP() {
- if (ConnectedTo?.urc === connectReturnCode.ETH) return;
- $.ajaxSetup({
- timeout: 3000 //Time in milliseconds
- });
- $.getJSON('/scan.json', async function () {
- await sleep(2000);
- $.getJSON('/ap.json', function (data) {
- if (data.length > 0) {
- // sort by signal strength
- data.sort(function (a, b) {
- const x = a.rssi;
- const y = b.rssi;
- // eslint-disable-next-line no-nested-ternary
- return x < y ? 1 : x > y ? -1 : 0;
- });
- apList = data;
- refreshAPHTML2(apList);
- }
- });
- });
- }
- function formatAP(ssid, rssi, auth) {
- const rssi_icon=rssiToIcon(rssi);
- const auth_icon={label:auth == 0 ? '🔓' : '🔒',icon:auth == 0 ? 'no_encryption' : 'lock'};
-
- return `<tr data-bs-toggle="modal" data-bs-target="#WifiConnectDialog"><td></td><td>${ssid}</td><td>
- <span class="material-icons" style="fill:white; display: inline" aria-label="${rssi_icon.label}" icon="${rssi_icon.icon}" >${getIcon(rssi_icon)}</span>
- </td><td>
- <span class="material-icons" aria-label="${auth_icon.label}" icon="${auth_icon.icon}">${getIcon(auth_icon)}</span>
- </td></tr>`;
- }
- function refreshAPHTML2(data) {
- let h = '';
- $('#wifiTable tr td:first-of-type').text('');
- $('#wifiTable tr').removeClass('table-success table-warning');
- if (data) {
- data.forEach(function (e) {
- h += formatAP(e.ssid, e.rssi, e.auth);
- });
- $('#wifiTable').html(h);
- }
- if ($('.manual_add').length == 0) {
- $('#wifiTable').append(formatAP('Manual add', 0, 0));
- $('#wifiTable tr:last').addClass('table-light text-dark').addClass('manual_add');
- }
- if (ConnectedTo.ssid && (ConnectedTo.urc === connectReturnCode.OK || ConnectedTo.urc === connectReturnCode.RESTORE)) {
- const wifiSelector = `#wifiTable td:contains("${ConnectedTo.ssid}")`;
- if ($(wifiSelector).filter(function () { return $(this).text() === ConnectedTo.ssid; }).length == 0) {
- $('#wifiTable').prepend(`${formatAP(ConnectedTo.ssid, ConnectedTo.rssi ?? 0, 0)}`);
- }
- $(wifiSelector).filter(function () { return $(this).text() === ConnectedTo.ssid; }).siblings().first().html('✓').parent().addClass((ConnectedTo.urc === connectReturnCode.OK ? 'table-success' : 'table-warning'));
- $('span#foot-if').html(`SSID: <strong>${ConnectedTo.ssid}</strong>, IP: <strong>${ConnectedTo.ip}</strong>`);
- $('#wifiStsIcon').html(rssiToIcon(ConnectedTo.rssi));
- }
- else if (ConnectedTo?.urc !== connectReturnCode.ETH) {
- $('span#foot-if').html('');
- }
- }
- function refreshETH() {
- if (ConnectedTo.urc === connectReturnCode.ETH) {
- $('span#foot-if').html(`Network: Ethernet, IP: <strong>${ConnectedTo.ip}</strong>`);
- }
- }
- function showTask(task) {
- console.debug(
- this.toLocaleString() +
- '\t' +
- task.nme +
- '\t' +
- task.cpu +
- '\t' +
- taskStates[task.st] +
- '\t' +
- task.minstk +
- '\t' +
- task.bprio +
- '\t' +
- task.cprio +
- '\t' +
- task.num
- );
- $('tbody#tasks').append(
- '<tr class="table-primary"><th scope="row">' +
- task.num +
- '</th><td>' +
- task.nme +
- '</td><td>' +
- task.cpu +
- '</td><td>' +
- taskStates[task.st] +
- '</td><td>' +
- task.minstk +
- '</td><td>' +
- task.bprio +
- '</td><td>' +
- task.cprio +
- '</td></tr>'
- );
- }
- function btExists(name) {
- return getBTSinkOpt(name).length > 0;
- }
- function getBTSinkOpt(name) {
- return $(`${btSinkNamesOptSel} option:contains('${name}')`);
- }
- function getMessages() {
- $.ajaxSetup({
- timeout: messageInterval //Time in milliseconds
- });
- $.getJSON('/messages.json', async function (data) {
- for (const msg of data) {
- const msgAge = msg.current_time - msg.sent_time;
- var msgTime = new Date();
- msgTime.setTime(msgTime.getTime() - msgAge);
- switch (msg.class) {
- case 'MESSAGING_CLASS_OTA':
- flashState.EventOTAMessageClass(msg.message);
- break;
- case 'MESSAGING_CLASS_STATS':
- // for task states, check structure : task_state_t
- var statsData = JSON.parse(msg.message);
- console.debug(
- msgTime.toLocalShort() +
- ' - Number of running tasks: ' +
- statsData.ntasks
- );
- console.debug(
- msgTime.toLocalShort() +
- '\tname' +
- '\tcpu' +
- '\tstate' +
- '\tminstk' +
- '\tbprio' +
- '\tcprio' +
- '\tnum'
- );
- if (statsData.tasks) {
- if ($('#tasks_sect').css('visibility') === 'collapse') {
- $('#tasks_sect').css('visibility', 'visible');
- }
- $('tbody#tasks').html('');
- statsData.tasks
- .sort(function (a, b) {
- return b.cpu - a.cpu;
- })
- .forEach(showTask, msgTime);
- } else if ($('#tasks_sect').css('visibility') === 'visible') {
- $('tbody#tasks').empty();
- $('#tasks_sect').css('visibility', 'collapse');
- }
- break;
- case 'MESSAGING_CLASS_SYSTEM':
- showMessage(msg, msgTime);
- break;
- case 'MESSAGING_CLASS_CFGCMD':
- var msgparts = msg.message.split(/([^\n]*)\n(.*)/gs);
- showCmdMessage(msgparts[1], msg.type, msgparts[2], true);
- break;
- case 'MESSAGING_CLASS_BT':
- if ($("#cfg-audio-bt_source-sink_name").is('input')) {
- var attr = $("#cfg-audio-bt_source-sink_name")[0].attributes;
- var attrs = '';
- for (var j = 0; j < attr.length; j++) {
- if (attr.item(j).name != "type") {
- attrs += `${attr.item(j).name} = "${attr.item(j).value}" `;
- }
- }
- var curOpt = $("#cfg-audio-bt_source-sink_name")[0].value;
- $("#cfg-audio-bt_source-sink_name").replaceWith(`<select id="cfg-audio-bt_source-sink_name" ${attrs}><option value="${curOpt}" data-bs-description="${curOpt}">${curOpt}</option></select> `);
- }
- JSON.parse(msg.message).forEach(function (btEntry) {
- //<input type="text" class="form-control bg-success" placeholder="name" hasvalue="true" longopts="sink_name" shortopts="n" checkbox="false" cmdname="cfg-audio-bt_source" id="cfg-audio-bt_source-sink_name" name="cfg-audio-bt_source-sink_name">
- //<select hasvalue="true" longopts="jack_behavior" shortopts="j" checkbox="false" cmdname="cfg-audio-general" id="cfg-audio-general-jack_behavior" name="cfg-audio-general-jack_behavior" class="form-control "><option>--</option><option>Headphones</option><option>Subwoofer</option></select>
- if (!btExists(btEntry.name)) {
- $("#cfg-audio-bt_source-sink_name").append(`<option>${btEntry.name}</option>`);
- showMessage({ type: msg.type, message: `BT Audio device found: ${btEntry.name} RSSI: ${btEntry.rssi} ` }, msgTime);
- }
- getBTSinkOpt(btEntry.name).attr('data-bs-description', `${btEntry.name} (${btEntry.rssi}dB)`)
- .attr('rssi', btEntry.rssi)
- .attr('value', btEntry.name)
- .text(`${btEntry.name} [${btEntry.rssi}dB]`).trigger('change');
- });
- $(btSinkNamesOptSel).append($(`${btSinkNamesOptSel} option`).remove().sort(function (a, b) {
- console.log(`${parseInt($(a).attr('rssi'))} < ${parseInt($(b).attr('rssi'))} ? `);
- return parseInt($(a).attr('rssi')) < parseInt($(b).attr('rssi')) ? 1 : -1;
- }));
- break;
- default:
- break;
- }
- }
- setTimeout(getMessages,messageInterval);
- }).fail(function (xhr, ajaxOptions, thrownError) {
-
- if (xhr.status == 404) {
- $('.orec').hide(); // system commands won't be available either
- messagesHeld = true;
- }
- else {
- handleExceptionResponse(xhr, ajaxOptions, thrownError);
- }
- if(xhr.status == 0 && xhr.readyState ==0){
- // probably a timeout. Target is rebooting?
- setTimeout(getMessages,messageInterval*2); // increase duration if a failure happens
- }
- else if(!messagesHeld){
- // 404 here means we rebooted to an old recovery
- setTimeout(getMessages,messageInterval); // increase duration if a failure happens
- }
-
- }
- );
- /*
- Minstk is minimum stack space left
- Bprio is base priority
- cprio is current priority
- nme is name
- st is task state. I provided a "typedef" that you can use to convert to text
- cpu is cpu percent used
- */
- }
- function handleRecoveryMode(data) {
- const locRecovery = data.recovery ?? 0;
- if (locRecovery === 1) {
- recovery = true;
- $('.recovery_element').show();
- $('.ota_element').hide();
- $('#boot-button').html('Reboot');
- $('#boot-form').attr('action', '/reboot_ota.json');
- } else {
- if(!recovery && messagesHeld){
- messagesHeld=false;
- setTimeout(getMessages,messageInterval); // increase duration if a failure happens
- }
- recovery = false;
-
- $('.recovery_element').hide();
- $('.ota_element').show();
- $('#boot-button').html('Recovery');
- $('#boot-form').attr('action', '/recovery.json');
- }
-
- }
- function hasConnectionChanged(data) {
- // gw: "192.168.10.1"
- // ip: "192.168.10.225"
- // netmask: "255.255.255.0"
- // ssid: "MyTestSSID"
- return (data.urc !== ConnectedTo.urc ||
- data.ssid !== ConnectedTo.ssid ||
- data.gw !== ConnectedTo.gw ||
- data.netmask !== ConnectedTo.netmask ||
- data.ip !== ConnectedTo.ip || data.rssi !== ConnectedTo.rssi)
- }
- function handleWifiDialog(data) {
- if ($('#WifiConnectDialog').is(':visible')) {
- if (ConnectedTo.ip) {
- $('#ipAddress').text(ConnectedTo.ip);
- }
- if (ConnectedTo.ssid) {
- $('#connectedToSSID').text(ConnectedTo.ssid);
- }
- if (ConnectedTo.gw) {
- $('#gateway').text(ConnectedTo.gw);
- }
- if (ConnectedTo.netmask) {
- $('#netmask').text(ConnectedTo.netmask);
- }
- if (ConnectingToSSID.Action === undefined || (ConnectingToSSID.Action && ConnectingToSSID.Action == ConnectingToActions.STS)) {
- $("*[class*='connecting']").hide();
- $('.connecting-status').show();
- }
- if (SystemConfig.ap_ssid) {
- $('#apName').text(SystemConfig.ap_ssid.value);
- }
- if (SystemConfig.ap_pwd) {
- $('#apPass').text(SystemConfig.ap_pwd.value);
- }
- if (!data) {
- return;
- }
- else {
- switch (data.urc) {
- case connectReturnCode.OK:
- if (data.ssid && data.ssid === ConnectingToSSID.ssid) {
- $("*[class*='connecting']").hide();
- $('.connecting-success').show();
- ConnectingToSSID.Action = ConnectingToActions.STS;
- }
- break;
- case connectReturnCode.FAIL:
- //
- if (ConnectingToSSID.Action != ConnectingToActions.STS && ConnectingToSSID.ssid == data.ssid) {
- $("*[class*='connecting']").hide();
- $('.connecting-fail').show();
- }
- break;
- case connectReturnCode.LOST:
- break;
- case connectReturnCode.RESTORE:
- if (ConnectingToSSID.Action != ConnectingToActions.STS && ConnectingToSSID.ssid != data.ssid) {
- $("*[class*='connecting']").hide();
- $('.connecting-fail').show();
- }
- break;
- case connectReturnCode.DISC:
- // that's a manual disconnect
- // if ($('#wifi-status').is(':visible')) {
- // $('#wifi-status').slideUp('fast', function() {});
- // $('span#foot-wifi').html('');
- // }
- break;
- default:
- break;
- }
- }
- }
- }
- function setIcons(offline){
- $('.material-icons').each(function (_index, entry) {
- entry.textContent = entry.attributes[offline?'aria-label':'icon'].value;
- });
- }
- function handleNetworkStatus(data) {
- setIcons(data.ssid==='');
- if (hasConnectionChanged(data) || !data.urc) {
- ConnectedTo = data;
- $(".if_eth").hide();
- $('.if_wifi').hide();
- if (!data.urc || ConnectedTo.urc != connectReturnCode.ETH) {
- $('.if_wifi').show();
- refreshAPHTML2();
- }
- else {
- $(".if_eth").show();
- refreshETH();
- }
- }
- handleWifiDialog(data);
- }
- function batteryToIcon(voltage) {
- /* Assuming Li-ion 18650s as a power source, 3.9V per cell, or above is treated
- as full charge (>75% of capacity). 3.4V is empty. The gauge is loosely
- following the graph here:
- https://learn.adafruit.com/li-ion-and-lipoly-batteries/voltages
- using the 0.2C discharge profile for the rest of the values.
- */
- for (const iconEntry of batIcons) {
- for (const entryRanges of iconEntry.ranges) {
- if (inRange(voltage, entryRanges.f, entryRanges.t)) {
- return { label: iconEntry.label, icon:iconEntry.icon};
- }
- }
- }
- return {label:'▪▪▪▪',icon:"battery_full"};
- }
- function checkStatus() {
- $.ajaxSetup({
- timeout: statusInterval //Time in milliseconds
- });
- $.getJSON('/status.json', function (data) {
- handleRecoveryMode(data);
- handleNVSVisible();
- handleNetworkStatus(data);
- handlebtstate(data);
- flashState.EventTargetStatus(data);
- if (data.project_name && data.project_name !== '') {
- project_name = data.project_name;
- }
- if (data.platform_name && data.platform_name !== '') {
- platform_name = data.platform_name;
- }
- if (board_model === '') board_model = project_name;
- if (board_model === '') board_model = 'Squeezelite-ESP32';
- if (data.version && data.version !== '') {
- versionName = data.version;
- $("#navtitle").html(`${board_model}${recovery ? '<br>[recovery]' : ''}`);
- $('span#foot-fw').html(`fw: <strong>${versionName}</strong>, mode: <strong>${recovery ? "Recovery" : project_name}</strong>`);
- } else {
- $('span#flash-status').html('');
- }
- if (data.Voltage) {
- const bat_icon=batteryToIcon(data.Voltage);
- $('#battery').html(`${getIcon(bat_icon)}`);
- $('#battery').attr("aria-label",bat_icon.label);
- $('#battery').attr("icon",bat_icon.icon);
- $('#battery').show();
- } else {
- $('#battery').hide();
- }
- if ((data.message ?? '') != '' && prevmessage != data.message) {
- // supporting older recovery firmwares - messages will come from the status.json structure
- prevmessage = data.message;
- showLocalMessage(data.message, 'MESSAGING_INFO')
- }
- is_i2c_locked = data.is_i2c_locked;
- if (is_i2c_locked) {
- $('flds-cfg-hw-preset').hide();
- }
- else {
- $('flds-cfg-hw-preset').show();
- }
- $("button[onclick*='handleReboot']").removeClass('rebooting');
- if (typeof lmsBaseUrl == "undefined" || data.lms_ip != prevLMSIP && data.lms_ip && data.lms_port) {
- const baseUrl = 'http://' + data.lms_ip + ':' + data.lms_port;
- prevLMSIP = data.lms_ip;
- $.ajax({
- url: baseUrl + '/plugins/SqueezeESP32/firmware/-check.bin',
- type: 'HEAD',
- dataType: 'text',
- cache: false,
- error: function () {
- // define the value, so we don't check it any more.
- lmsBaseUrl = '';
- },
- success: function () {
- lmsBaseUrl = baseUrl;
- }
- });
- }
- $('#o_jack').css({ display: Number(data.Jack) ? 'inline' : 'none' });
- setTimeout(checkStatus,statusInterval);
- }).fail(function (xhr, ajaxOptions, thrownError) {
- handleExceptionResponse(xhr, ajaxOptions, thrownError);
- if(xhr.status == 0 && xhr.readyState ==0){
- // probably a timeout. Target is rebooting?
- setTimeout(checkStatus,messageInterval*2); // increase duration if a failure happens
- }
- else {
- setTimeout(checkStatus,messageInterval); // increase duration if a failure happens
- }
- });
- }
- // eslint-disable-next-line no-unused-vars
- window.runCommand = function (button, reboot) {
- let cmdstring = button.attributes.cmdname.value;
- showCmdMessage(
- button.attributes.cmdname.value,
- 'MESSAGING_INFO',
- 'Executing.',
- false
- );
- const fields = document.getElementById('flds-' + cmdstring);
- const allfields = fields?.querySelectorAll('select,input');
- if (cmdstring === 'cfg-hw-preset') return handleHWPreset(allfields, reboot);
- cmdstring += ' ';
- if (fields) {
- for (const field of allfields) {
- let qts = '';
- let opt = '';
- let attr = field.attributes;
- let isSelect = $(field).is('select');
- const hasValue = attr?.hasvalue?.value === 'true';
- const validVal = (isSelect && field.value !== '--') || (!isSelect && field.value !== '');
- if (!hasValue || hasValue && validVal) {
- if (attr?.longopts?.value !== 'undefined') {
- opt += '--' + attr?.longopts?.value;
- } else if (attr?.shortopts?.value !== 'undefined') {
- opt = '-' + attr.shortopts.value;
- }
- if (attr?.hasvalue?.value === 'true') {
- if (attr?.value !== '') {
- qts = /\s/.test(field.value) ? '"' : '';
- cmdstring += opt + ' ' + qts + field.value + qts + ' ';
- }
- } else {
- // this is a checkbox
- if (field?.checked) {
- cmdstring += opt + ' ';
- }
- }
- }
- }
- }
- console.log(cmdstring);
- const data = {
- timestamp: Date.now(),
- };
- data.command = cmdstring;
- $.ajax({
- url: '/commands.json',
- dataType: 'text',
- method: 'POST',
- cache: false,
- contentType: 'application/json; charset=utf-8',
- data: JSON.stringify(data),
- error: function (xhr, _ajaxOptions, thrownError) {
- var cmd = JSON.parse(this.data).command;
- if (xhr.status == 404) {
- showCmdMessage(
- cmd.substr(0, cmd.indexOf(' ')),
- 'MESSAGING_ERROR',
- `${recovery ? 'Limited recovery mode active. Unsupported action ' : 'Unexpected error while processing command'}`,
- true
- );
- }
- else {
- handleExceptionResponse(xhr, _ajaxOptions, thrownError);
- showCmdMessage(
- cmd.substr(0, cmd.indexOf(' ') - 1),
- 'MESSAGING_ERROR',
- `Unexpected error ${(thrownError !== '') ? thrownError : 'with return status = ' + xhr.status}`,
- true
- );
- }
- },
- success: function (response) {
- $('.orec').show();
- console.log(response);
- if (
- JSON.parse(response).Result === 'Success' &&
- reboot
- ) {
- delayReboot(2500, button.attributes.cmdname.value);
- }
- },
- });
- }
- function getLongOps(data, name, longopts) {
- return data.values[name] !== undefined ? data.values[name][longopts] : "";
- }
- function getCommands() {
- $.ajaxSetup({
- timeout: 7000 //Time in milliseconds
- });
- $.getJSON('/commands.json', function (data) {
- console.log(data);
- $('.orec').show();
- data.commands.forEach(function (command) {
- if ($('#flds-' + command.name).length === 0) {
- const cmdParts = command.name.split('-');
- const isConfig = cmdParts[0] === 'cfg';
- const targetDiv = '#tab-' + cmdParts[0] + '-' + cmdParts[1];
- let innerhtml = '';
- innerhtml += `<div class="card text-white mb-3"><div class="card-header">${command.help.encodeHTML().replace(/\n/g, '<br />')}</div><div class="card-body"><fieldset id="flds-${command.name}">`;
- if (command.argtable) {
- command.argtable.forEach(function (arg) {
- let placeholder = arg.datatype || '';
- const ctrlname = command.name + '-' + arg.longopts;
- const curvalue = getLongOps(data, command.name, arg.longopts);
- let attributes = 'hasvalue=' + arg.hasvalue + ' ';
- attributes += 'longopts="' + arg.longopts + '" ';
- attributes += 'shortopts="' + arg.shortopts + '" ';
- attributes += 'checkbox=' + arg.checkbox + ' ';
- attributes += 'cmdname="' + command.name + '" ';
- attributes +=
- 'id="' +
- ctrlname +
- '" name="' +
- ctrlname +
- '" hasvalue="' +
- arg.hasvalue +
- '" ';
- let extraclass = arg.mincount > 0 ? 'bg-success' : '';
- if (arg.glossary === 'hidden') {
- attributes += ' style="visibility: hidden;"';
- }
- if (arg.checkbox) {
- innerhtml += `<div class="form-check"><label class="form-check-label"><input type="checkbox" ${attributes} class="form-check-input ${extraclass}" value="" >${arg.glossary.encodeHTML()}</label>`;
- } else {
- innerhtml += `<div class="form-group" ><label for="${ctrlname}">${arg.glossary.encodeHTML()}</label>`;
- if (placeholder.includes('|')) {
- extraclass = placeholder.startsWith('+') ? ' multiple ' : '';
- placeholder = placeholder
- .replace('<', '')
- .replace('=', '')
- .replace('>', '');
- innerhtml += `<select ${attributes} class="form-control ${extraclass}" >`;
- placeholder = '--|' + placeholder;
- placeholder.split('|').forEach(function (choice) {
- innerhtml += '<option >' + choice + '</option>';
- });
- innerhtml += '</select>';
- } else {
- innerhtml += `<input type="text" class="form-control ${extraclass}" placeholder="${placeholder}" ${attributes}>`;
- }
- }
- innerhtml += `${arg.checkbox ? '</div>' : ''}<small class="form-text text-muted">Previous value: ${arg.checkbox ? (curvalue ? 'Checked' : 'Unchecked') : (curvalue || '')}</small>${arg.checkbox ? '' : '</div>'}`;
- });
- }
- innerhtml += `<div style="margin-top: 16px;">
- <div class="toast hide" role="alert" aria-live="assertive" aria-atomic="true" id="toast_${command.name}">
- <div class="toast-header">
- <strong class="mr-auto">Result</strong
- <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
- </div>
- <div class="toast-body" id="msg_${command.name}"></div>
- </div>`;
- if (isConfig) {
- innerhtml +=
- `<button type="submit" class="btn btn-info sclk" id="btn-save-${command.name}" cmdname="${command.name}">Save</button>
- <button type="submit" class="btn btn-warning cclk" id="btn-commit-${command.name}" cmdname="${command.name}">Apply</button>`;
- } else {
- innerhtml += `<button type="submit" class="btn btn-success sclk" id="btn-run-${command.name}" cmdname="${command.name}">Execute</button>`;
- }
- innerhtml += '</div></fieldset></div></div>';
- if (isConfig) {
- $(targetDiv).append(innerhtml);
- } else {
- $('#commands-list').append(innerhtml);
- }
- }
- });
- $(".sclk").off('click').on('click', function () { runCommand(this, false); });
- $(".cclk").off('click').on('click', function () { runCommand(this, true); });
- data.commands.forEach(function (command) {
- $('[cmdname=' + command.name + ']:input').val('');
- $('[cmdname=' + command.name + ']:checkbox').prop('checked', false);
- if (command.argtable) {
- command.argtable.forEach(function (arg) {
- const ctrlselector = '#' + command.name + '-' + arg.longopts;
- const ctrlValue = getLongOps(data, command.name, arg.longopts);
- if (arg.checkbox) {
- $(ctrlselector)[0].checked = ctrlValue;
- } else {
- if (ctrlValue !== undefined) {
- $(ctrlselector)
- .val(ctrlValue)
- .trigger('change');
- }
- if (
- $(ctrlselector)[0].value.length === 0 &&
- (arg.datatype || '').includes('|')
- ) {
- $(ctrlselector)[0].value = '--';
- }
- }
- });
- }
- });
- loadPresets();
- }).fail(function (xhr, ajaxOptions, thrownError) {
- if (xhr.status == 404) {
- $('.orec').hide();
- }
- else {
- handleExceptionResponse(xhr, ajaxOptions, thrownError);
- }
- $('#commands-list').empty();
- });
- }
- function getConfig() {
- $.ajaxSetup({
- timeout: 7000 //Time in milliseconds
- });
- $.getJSON('/config.json', function (entries) {
- $('#nvsTable tr').remove();
- const data = (entries.config ? entries.config : entries);
- SystemConfig = data;
- Object.keys(data)
- .sort()
- .forEach(function (key) {
- let val = data[key].value;
- if (key === 'autoexec') {
- if (data.autoexec.value === '0') {
- $('#disable-squeezelite')[0].checked = true;
- } else {
- $('#disable-squeezelite')[0].checked = false;
- }
- } else if (key === 'autoexec1') {
- const re = /-o\s?(["][^"]*["]|[^-]+)/g;
- const m = re.exec(val);
- if (m[1].toUpperCase().startsWith('I2S')) {
- handleTemplateTypeRadio('i2s');
- } else if (m[1].toUpperCase().startsWith('SPDIF')) {
- handleTemplateTypeRadio('spdif');
- } else if (m[1].toUpperCase().startsWith('"BT')) {
- handleTemplateTypeRadio('bt');
- }
- } else if (key === 'host_name') {
- val = val.replaceAll('"', '');
- $('input#dhcp-name1').val(val);
- $('input#dhcp-name2').val(val);
- $('#player').val(val);
- document.title = val;
- hostName = val;
- } else if (key === 'rel_api') {
- releaseURL = val;
- }
- else if (key === 'enable_airplay') {
- $("#s_airplay").css({ display: isEnabled(val) ? 'inline' : 'none' })
- }
- else if (key === 'enable_cspot') {
- $("#s_cspot").css({ display: isEnabled(val) ? 'inline' : 'none' })
- }
- else if (key == 'preset_name') {
- preset_name = val;
- }
- else if (key == 'board_model') {
- board_model = val;
- }
- $('tbody#nvsTable').append(
- '<tr>' +
- '<td>' +
- key +
- '</td>' +
- "<td class='value'>" +
- "<input type='text' class='form-control nvs' id='" +
- key +
- "' nvs_type=" +
- data[key].type +
- ' >' +
- '</td>' +
- '</tr>'
- );
- $('input#' + key).val(data[key].value);
- });
- $('tbody#nvsTable').append(
- "<tr><td><input type='text' class='form-control' id='nvs-new-key' placeholder='new key'></td><td><input type='text' class='form-control' id='nvs-new-value' placeholder='new value' nvs_type=33 ></td></tr>"
- );
- if (entries.gpio) {
- $('#pins').show();
- $('tbody#gpiotable tr').remove();
- entries.gpio.forEach(function (gpioEntry) {
- $('tbody#gpiotable').append(
- '<tr class=' +
- (gpioEntry.fixed ? 'table-secondary' : 'table-primary') +
- '><th scope="row">' +
- gpioEntry.group +
- '</th><td>' +
- gpioEntry.name +
- '</td><td>' +
- gpioEntry.gpio +
- '</td><td>' +
- (gpioEntry.fixed ? 'Fixed' : 'Configuration') +
- '</td></tr>'
- );
- });
- }
- else {
- $('#pins').hide();
- }
- }).fail(function (xhr, ajaxOptions, thrownError) {
- handleExceptionResponse(xhr, ajaxOptions, thrownError);
- });
- }
- function showLocalMessage(message, severity) {
- const msg = {
- message: message,
- type: severity,
- };
- showMessage(msg, new Date());
- }
- function showMessage(msg, msgTime) {
- let color = 'table-success';
- if (msg.type === 'MESSAGING_WARNING') {
- color = 'table-warning';
- if (messageseverity === 'MESSAGING_INFO') {
- messageseverity = 'MESSAGING_WARNING';
- }
- } else if (msg.type === 'MESSAGING_ERROR') {
- if (
- messageseverity === 'MESSAGING_INFO' ||
- messageseverity === 'MESSAGING_WARNING'
- ) {
- messageseverity = 'MESSAGING_ERROR';
- }
- color = 'table-danger';
- }
- if (++messagecount > 0) {
- $('#msgcnt').removeClass('badge-success');
- $('#msgcnt').removeClass('badge-warning');
- $('#msgcnt').removeClass('badge-danger');
- $('#msgcnt').addClass(pillcolors[messageseverity]);
- $('#msgcnt').text(messagecount);
- }
- $('#syslogTable').append(
- "<tr class='" +
- color +
- "'>" +
- '<td>' +
- msgTime.toLocalShort() +
- '</td>' +
- '<td>' +
- msg.message.encodeHTML() +
- '</td>' +
- '</tr>'
- );
- }
- function inRange(x, min, max) {
- return (x - min) * (x - max) <= 0;
- }
- function sleep(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
- }
|