| 
					
				 | 
			
			
				@@ -112,14 +112,16 @@ const flash_status_codes = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   REBOOT_TO_RECOVERY: 2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SET_FWURL: 5, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   FLASHING: 6, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  DONE: 7 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  DONE: 7, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  UPLOADING: 8, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ERROR: 9 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let flash_state=flash_status_codes.FLASH_NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let flash_ota_dsc=''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let flash_ota_pct=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let older_recovery=false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 function isFlashExecuting(data){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return data.ota_dsc!='' || data.ota_pct>0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return (flash_state!=flash_status_codes.UPLOADING ) && (data.ota_dsc!='' || data.ota_pct>0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 function post_config(data){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   let confPayload={ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -140,16 +142,21 @@ function process_ota_event(data){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if(data.ota_dsc){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     flash_ota_dsc=data.ota_dsc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if(data.ota_pct){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if( data.ota_pct != undefined){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     flash_ota_pct=data.ota_pct; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if(isFlashExecuting(data)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(flash_state==flash_status_codes.ERROR){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else if(isFlashExecuting(data)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     flash_state=flash_status_codes.FLASHING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if(flash_state==flash_status_codes.FLASHING){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else if(flash_state==flash_status_codes.FLASHING ){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(flash_ota_pct ==100){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // we were processing OTA, and we've reached 100% 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       flash_state=flash_status_codes.DONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      $('#flashfilename').val(''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else if(flash_ota_pct<0 && older_recovery){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // we were processing OTA on an older recovery and we missed the  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -161,11 +168,48 @@ function process_ota_event(data){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       flash_state=flash_status_codes.DONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else if(flash_state ==flash_status_codes.UPLOADING){  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(flash_ota_pct ==100){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // we were processing OTA, and we've reached 100% 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // reset the progress bar  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      flash_ota_pct = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      flash_state=flash_status_codes.FLASHING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function set_ota_error(message){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  flash_state=flash_status_codes.ERROR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  handle_flash_state({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ota_pct: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ota_dsc: message, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    event: flash_events.SET_ERROR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  });   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function show_update_dialog(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  $('#otadiv').modal(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (flash_ota_pct >= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      update_progress(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (flash_ota_dsc !== '') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      $('span#flash-status').html(flash_ota_dsc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const flash_events={ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  SET_ERROR: function(data){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(data.ota_dsc){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      flash_ota_dsc=data.ota_dsc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      flash_ota_dsc = 'Error'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    flash_ota_pct=data.ota_pct??0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    $('#fwProgressLabel').parent().addClass('bg-danger'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    update_progress(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    show_update_dialog(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   START_OTA : function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (flash_state == flash_status_codes.NONE || flash_state == undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      console.log('Starting OTA process'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (flash_state == flash_status_codes.NONE || flash_state == flash_status_codes.ERROR || flash_state == undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      $('#fwProgressLabel').parent().removeClass('bg-danger'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       flash_state=flash_status_codes.REBOOT_TO_RECOVERY; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if(!recovery){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         flash_ota_dsc = 'Starting recovery mode...'; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -181,13 +225,19 @@ const flash_events={ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           cache: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           contentType: 'application/json; charset=utf-8', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           data: JSON.stringify(data), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          error: handleExceptionResponse, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          error:  function(xhr, _ajaxOptions, thrownError){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            set_ota_error(`Unexpected error while trying to restart to recovery. (status=${xhr.status??''}, error=${thrownError??''} ) `); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           complete: function(response) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             console.log(response.responseText); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         });      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        flash_ota_dsc='Starting Update'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      show_update_dialog(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       console.warn('Unexpected status while starting flashing'); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -195,17 +245,49 @@ const flash_events={ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   FOUND_RECOVERY: function(data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     console.log(JSON.stringify(data)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const url=$('#fw-url-input').val(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(flash_state == flash_status_codes.REBOOT_TO_RECOVERY){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        flash_ota_dsc = 'Recovery mode found. Flashing device.'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        flash_state= flash_status_codes.SET_FWURL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let confData= { fwurl: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              value: $('#fw-url-input').val(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              type: 33, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        post_config(confData); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const fileInput = $('#flashfilename')[0].files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (fileInput.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          flash_ota_dsc = 'Sending file to device.'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          flash_state= flash_status_codes.UPLOADING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const uploadPath = '/flash.json'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const xhttp = new XMLHttpRequest(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //      xhrObj.upload.addEventListener("loadstart", loadStartFunction, false);   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          xhttp.upload.addEventListener("progress", progressFunction, false);   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          //xhrObj.upload.addEventListener("load", transferCompleteFunction, false);   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          xhttp.onreadystatechange = function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (xhttp.readyState === 4) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              if(xhttp.status === 0 || xhttp.status === 404) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                set_ota_error(`Upload Failed. Recovery version might not support uploading. Please use web update instead.`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $('#flashfilename').val(''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          xhttp.open('POST', uploadPath, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          xhttp.send(fileInput[0] ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if(url==''){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          flash_state= flash_status_codes.NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          flash_ota_dsc = 'Saving firmware URL location.'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          flash_state= flash_status_codes.SET_FWURL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          let confData= { fwurl: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                value: $('#fw-url-input').val(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                type: 33, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          post_config(confData);           
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        show_update_dialog(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  PROCESS_OTA_UPLOAD: function(data){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    flash_state= flash_status_codes.UPLOADING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    process_ota_event(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    show_update_dialog(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   PROCESS_OTA_STATUS: function(data){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(data.ota_pct>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       older_recovery = true; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -218,22 +300,33 @@ const flash_events={ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       flash_state=flash_status_codes.NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       $('#rTable tr.release').removeClass('table-success table-warning'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       $('#fw-url-input').val(''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      $('#otadiv').modal('hide'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       process_ota_event(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if(flash_state && (flash_state >flash_status_codes.NONE && flash_ota_pct>=0) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        show_update_dialog(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   PROCESS_OTA: function(data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     process_ota_event(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(flash_state && (flash_state >flash_status_codes.NONE && flash_ota_pct>=0) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      show_update_dialog(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 window.hideSurrounding = function(obj){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   $(obj).parent().parent().hide(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function update_progress(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  $('.progress-bar') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    .css('width', flash_ota_pct + '%') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    .attr('aria-valuenow', flash_ota_pct) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    .text(flash_ota_pct+'%') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  $('.progress-bar').html((flash_state==flash_status_codes.DONE?100:flash_ota_pct) + '%'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 function handle_flash_state(data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if(data.event)  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     data.event(data); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -243,37 +336,33 @@ function handle_flash_state(data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if(flash_state && flash_state >flash_status_codes.NONE && flash_ota_pct>=0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    $('#otadiv').modal(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (flash_ota_pct !== 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      $('.progress-bar') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .css('width', flash_ota_pct + '%') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .attr('aria-valuenow', flash_ota_pct) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        .text(flash_ota_pct+'%') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      $('.progress-bar').html((flash_state==flash_status_codes.DONE?100:flash_ota_pct) + '%'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (flash_ota_dsc !== '') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      $('span#flash-status').html(flash_ota_dsc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    flash_ota_pct=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    flash_ota_dsc=''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 window.hFlash = function(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // reset file upload selection if any; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  $('#flashfilename').val(''); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   handle_flash_state({ event: flash_events.START_OTA, url: $('#fw-url-input').val() }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 window.handleReboot = function(link){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if(link=='reboot_ota'){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    $('#reboot_ota_nav').removeClass('active'); delayReboot(500,'', 'reboot_ota'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    $('#reboot_ota_nav').removeClass('active').prop("disabled",true); delayReboot(500,'', 'reboot_ota'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     $('#reboot_nav').removeClass('active'); delayReboot(500,'',link); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+function progressFunction(evt){   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // if (evt.lengthComputable) {   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //   progressBar.max = evt.total;   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //   progressBar.value = evt.loaded;   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //   percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // }   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  handle_flash_state({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ota_pct: ( Math.round(evt.loaded / evt.total * 100)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ota_dsc: ('Uploading file to device'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    event: flash_events.PROCESS_OTA_UPLOAD 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  });   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 function handlebtstate(data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   let icon = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   let tt = ''; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -373,6 +462,7 @@ let LastCommandsState = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 var output = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let hostName = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let versionName='Squeezelite-ESP32'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let prevmessage=''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let project_name=versionName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let platform_name=versionName; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 let btSinkNamesOptSel='#cfg-audio-bt_source-sink_name'; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -515,6 +605,7 @@ function delayReboot(duration, cmdname, ota = 'reboot') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         showLocalMessage('System is rebooting.\n', 'MESSAGING_WARNING'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       console.log('now triggering reboot'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      $("button[onclick*='handleReboot']").addClass('rebooting'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       $.ajax({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         url: data.url, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         dataType: 'text', 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -619,7 +710,13 @@ window.handleDisconnect = function(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        }), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -777,40 +874,15 @@ $(document).ready(function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   $('#save-nvs').on('click', function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     post_config(getConfigJson(false)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   $('#fwUpload').on('click', function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const uploadPath = '/flash.json'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!recovery) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      $('#flash-status').text('Rebooting to recovery.  Please try again'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      window.handleReboot(false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const fileInput = document.getElementById('flashfilename').files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (fileInput.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       alert('No file selected!'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const file = fileInput[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const xhttp = new XMLHttpRequest(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      xhttp.onreadystatechange = function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (xhttp.readyState === 4) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (xhttp.status === 200) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            showLocalMessage(xhttp.responseText, 'MESSAGING_INFO'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } else if (xhttp.status === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            showLocalMessage( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              'Upload connection was closed abruptly!', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              'MESSAGING_ERROR' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            showLocalMessage( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              xhttp.status + ' Error!\n' + xhttp.responseText, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              'MESSAGING_ERROR' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      xhttp.open('POST', uploadPath, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      xhttp.send(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      handle_flash_state({ event: flash_events.START_OTA, file: fileInput[0] }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    $('[name=output-tmpl]').on('click', function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     handleTemplateTypeRadio(this.id); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -874,13 +946,9 @@ $(document).ready(function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       $('#searchfw').css('display', 'inline'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if(platform_name!=='' && $('.upf').filter(function(){ return $(this).text().toUpperCase()===platform_name.toUpperCase()}).length>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        $('#splf').val(platform_name).trigger('input'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      else if($('.upf').filter(function(){ return $(this).text().toUpperCase()===project_name.toUpperCase()}).length>0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        $('#splf').val(project_name).trigger('input'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if(!setPlatformFilter(platform_name)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        setPlatformFilter(project_name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       $('#rTable tr.release').on('click', function() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         var url=this.attributes['fwurl'].value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (lmsBaseUrl) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1221,7 +1289,16 @@ function getMessages() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }).fail(handleExceptionResponse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }).fail(function(xhr, ajaxOptions, thrownError){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if(xhr.status==404){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $('.orec').hide(); // system commands won't be available either 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        handleExceptionResponse(xhr, ajaxOptions, thrownError); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Minstk is minimum stack space left 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1408,6 +1485,12 @@ function checkStatus() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 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') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    $("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; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1489,9 +1572,29 @@ window.runCommand = function(button, reboot) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cache: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     contentType: 'application/json; charset=utf-8', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     data: JSON.stringify(data), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    error: handleExceptionResponse, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    complete: function(response) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // var returnedResponse = JSON.parse(response.responseText); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      $('.orec').show(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       console.log(response.responseText); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         response.responseText && 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1509,6 +1612,7 @@ function getLongOps(data, name, longopts){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 function getCommands() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   $.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('-'); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1664,7 +1768,13 @@ function getCommands() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }).fail(function(xhr, ajaxOptions, thrownError) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    handleExceptionResponse(xhr, ajaxOptions, thrownError); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(xhr.status==404){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      $('.orec').hide(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      handleExceptionResponse(xhr, ajaxOptions, thrownError); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     $('#commands-list').empty(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     blockAjax = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1725,6 +1835,7 @@ function getConfig() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       "<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( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1742,6 +1853,9 @@ function getConfig() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      $('#pins').hide(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }).fail(function(xhr, ajaxOptions, thrownError) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     handleExceptionResponse(xhr, ajaxOptions, thrownError); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     blockAjax = false; 
			 |