@@ -78,6 +78,8 @@ const CoordinateTypes = {
7878var convertedCoordinate = 0.0 ;
7979var coordinateInputType = CoordinateTypes . COORDINATE_INPUT_TYPE_DD ;
8080
81+ var initialSettings = { } ;
82+
8183function parseIncoming ( msg ) {
8284 //console.log("Incoming message: " + msg);
8385
@@ -226,6 +228,9 @@ function parseIncoming(msg) {
226228 hide ( "constellationSbas" ) ; //Not supported on UM980
227229 hide ( "constellationNavic" ) ; //Not supported on UM980
228230
231+ show ( "galileoHasSetting" ) ;
232+ hide ( "lg290pGnssSettings" ) ;
233+
229234 show ( "measurementRateInput" ) ;
230235
231236 show ( "loraConfig" ) ;
@@ -326,7 +331,7 @@ function parseIncoming(msg) {
326331 hide ( "logToSDCard" ) ; //No SD card on Torch
327332
328333 hide ( "constellationSbas" ) ; //Not supported on LG290P
329- show ( "constellationNavic" ) ;
334+ show ( "constellationNavic" ) ;
330335 show ( "galileoHasSetting" ) ;
331336 show ( "lg290pGnssSettings" ) ;
332337 hide ( "tiltConfig" ) ; //Not supported on Torch X2
@@ -711,6 +716,7 @@ function parseIncoming(msg) {
711716 ge ( "enableARPLogging" ) . dispatchEvent ( new CustomEvent ( 'change' ) ) ;
712717 ge ( "enableAutoFirmwareUpdate" ) . dispatchEvent ( new CustomEvent ( 'change' ) ) ;
713718 ge ( "enableAutoReset" ) . dispatchEvent ( new CustomEvent ( 'change' ) ) ;
719+ ge ( "enableGalileoHas" ) . dispatchEvent ( new CustomEvent ( 'change' ) ) ;
714720
715721 updateECEFList ( ) ;
716722 updateGeodeticList ( ) ;
@@ -720,9 +726,38 @@ function parseIncoming(msg) {
720726 dhcpEthernet ( ) ;
721727 updateLatLong ( ) ;
722728 updateCorrectionsPriorities ( ) ;
729+
730+ // Create copy of settings, send only changes when 'Save Configuration' is pressed
731+ saveInitialSettings ( ) ;
723732 }
724733}
725734
735+ // Save the current state of settings
736+ function saveInitialSettings ( ) {
737+ initialSettings = { } ; // Clear previous settings
738+
739+ // Save input boxes and dropdowns
740+ var clsElements = document . querySelectorAll ( ".form-control, .form-dropdown" ) ;
741+ for ( let x = 0 ; x < clsElements . length ; x ++ ) {
742+ initialSettings [ clsElements [ x ] . id ] = clsElements [ x ] . value ;
743+ }
744+
745+ // Save checkboxes and radio buttons
746+ clsElements = document . querySelectorAll ( ".form-check-input:not(.fileManagerCheck), .form-radio" ) ;
747+ for ( let x = 0 ; x < clsElements . length ; x ++ ) {
748+ // Store boolean values for easy comparison
749+ initialSettings [ clsElements [ x ] . id ] = clsElements [ x ] . checked . toString ( ) ;
750+ }
751+
752+ // Save corrections priorities
753+ for ( let x = 0 ; x < numCorrectionsSources ; x ++ ) {
754+ initialSettings [ "correctionsPriority_" + correctionsSourceNames [ x ] ] = correctionsSourcePriorities [ x ] . toString ( ) ;
755+ }
756+
757+ // Note: recordsECEF and recordsGeodetic change very little so instead
758+ // of creating copy here, we will resend any entered coordinates every time.
759+ }
760+
726761function hide ( id ) {
727762 ge ( id ) . style . display = "none" ;
728763}
@@ -738,39 +773,62 @@ function isElementShown(id) {
738773 return ( false ) ;
739774}
740775
741- //Create CSV of all setting data
776+ //Create CSV of all setting data that has changed from the original given to us
742777function sendData ( ) {
743778 var settingCSV = "" ;
779+ var changedCount = 0 ;
744780
745- //Input boxes
781+ // Check input boxes and dropdowns
746782 var clsElements = document . querySelectorAll ( ".form-control, .form-dropdown" ) ;
747783 for ( let x = 0 ; x < clsElements . length ; x ++ ) {
748- settingCSV += clsElements [ x ] . id + "," + clsElements [ x ] . value + "," ;
784+ var id = clsElements [ x ] . id ;
785+ var currentValue = clsElements [ x ] . value ;
786+ if ( initialSettings [ id ] !== currentValue ) {
787+ settingCSV += id + "," + currentValue + "," ;
788+ changedCount ++ ;
789+ }
749790 }
750791
751- //Check boxes, radio buttons
752- //Remove file manager files
792+ // Check boxes, radio buttons
753793 clsElements = document . querySelectorAll ( ".form-check-input:not(.fileManagerCheck), .form-radio" ) ;
754794 for ( let x = 0 ; x < clsElements . length ; x ++ ) {
755- settingCSV += clsElements [ x ] . id + "," + clsElements [ x ] . checked + "," ;
795+ var id = clsElements [ x ] . id ;
796+ // Store boolean as string 'true'/'false' for consistent comparison with initialSettings
797+ var currentValue = clsElements [ x ] . checked . toString ( ) ;
798+ if ( initialSettings [ id ] !== currentValue ) {
799+ settingCSV += id + "," + currentValue + "," ;
800+ changedCount ++ ;
801+ }
756802 }
757803
804+ // Records (ECEF and Geodetic) - For simplicity, we send the full list if any list element exists.
758805 for ( let x = 0 ; x < recordsECEF . length ; x ++ ) {
759806 settingCSV += "stationECEF" + x + ',' + recordsECEF [ x ] + "," ;
760807 }
761-
762808 for ( let x = 0 ; x < recordsGeodetic . length ; x ++ ) {
763809 settingCSV += "stationGeodetic" + x + ',' + recordsGeodetic [ x ] + "," ;
764810 }
765811
812+ // Corrections Priorities
766813 for ( let x = 0 ; x < correctionsSourceNames . length ; x ++ ) {
767- settingCSV += "correctionsPriority_" + correctionsSourceNames [ x ] + ',' + correctionsSourcePriorities [ x ] + "," ;
814+ var id = "correctionsPriority_" + correctionsSourceNames [ x ] ;
815+ var currentValue = correctionsSourcePriorities [ x ] . toString ( ) ;
816+ if ( initialSettings [ id ] !== currentValue ) {
817+ settingCSV += id + ',' + currentValue + "," ;
818+ changedCount ++ ;
819+ }
768820 }
769821
770- console . log ( "Sending: " + settingCSV ) ;
771- websocket . send ( settingCSV ) ;
822+ console . log ( "Sending " + changedCount + " changed settings: " + settingCSV ) ;
772823
773- sendDataTimeout = setTimeout ( sendData , 2000 ) ;
824+ // Only send if there are changes (plus the always-sent records)
825+ if ( settingCSV . length > 0 ) {
826+ websocket . send ( settingCSV ) ;
827+ sendDataTimeout = setTimeout ( sendData , 2000 ) ;
828+ } else {
829+ // If nothing changed, immediately report success.
830+ showSuccess ( 'saveBtn' , "No changes detected." ) ;
831+ }
774832}
775833
776834function showError ( id , errorText ) {
@@ -876,7 +934,7 @@ function validateFields() {
876934 if ( isElementShown ( "lg290pGnssSettings" ) == true ) {
877935 checkElementValue ( "rtcmMinElev" , - 90 , 90 , "Must be between -90 and 90" , "collapseGNSSConfig" ) ;
878936 }
879- if ( ge ( "enableGalileoHas" ) . checked == true ) {
937+ if ( isElementShown ( "configurePppSetting" ) == true ) {
880938 checkElementStringSpacesNoCommas ( "configurePPP" , 1 , 30 , "Must be 1 to 30 characters. Separated by spaces. Commas not allowed" , "collapseGNSSConfig" ) ;
881939 }
882940 if ( ge ( "enableNtripClient" ) . checked == true ) {
@@ -2006,6 +2064,20 @@ document.addEventListener("DOMContentLoaded", (event) => {
20062064 adjustHAE ( ) ;
20072065 } ) ;
20082066
2067+ ge ( "enableGalileoHas" ) . addEventListener ( "change" , function ( ) {
2068+ if ( ( isElementShown ( "galileoHasSetting" ) == true ) && ( isElementShown ( "lg290pGnssSettings" ) == true ) ) {
2069+ if ( ge ( "enableGalileoHas" ) . checked == true ) {
2070+ show ( "configurePppSetting" ) ;
2071+ }
2072+ else {
2073+ hide ( "configurePppSetting" ) ;
2074+ }
2075+ }
2076+ else {
2077+ hide ( "configurePppSetting" ) ; // Hide on Torch UM980 - i.e. non-LG290P
2078+ }
2079+ } ) ;
2080+
20092081 for ( let y = 0 ; y < numCorrectionsSources ; y ++ ) {
20102082 var buttonName = "corrPrioButton" + y ;
20112083 ge ( buttonName ) . addEventListener ( "click" , function ( ) {
0 commit comments