@@ -22,6 +22,9 @@ import { Row } from "./components/params/row.jsx"
2222
2323// Redux
2424import { useDispatch , useSelector } from "react-redux"
25+ import LoadParamsFileModal from "./components/params/loadParamsFileModal.jsx"
26+ import { EXCLUDE_PARAMS_LOAD } from "./helpers/mavlinkConstants.js"
27+ import { showErrorNotification } from "./helpers/notification.js"
2528import { selectConnectedToDrone } from "./redux/slices/droneConnectionSlice.js"
2629import {
2730 emitRefreshParams ,
@@ -36,9 +39,22 @@ import {
3639 selectShownParams ,
3740 setFetchingVars ,
3841 setHasFetchedOnce ,
42+ setLoadedFileName ,
43+ setLoadedParams ,
44+ setLoadParamsFileModalOpen ,
3945 setShownParams ,
4046} from "./redux/slices/paramsSlice.js"
4147
48+ function cleanFloat ( value , decimals = 5 ) {
49+ if ( typeof value === "number" ) {
50+ return Number ( value . toFixed ( decimals ) )
51+ }
52+ if ( ! isNaN ( value ) ) {
53+ return Number ( parseFloat ( value ) . toFixed ( decimals ) )
54+ }
55+ return value
56+ }
57+
4258export default function Params ( ) {
4359 const dispatch = useDispatch ( )
4460 const connected = useSelector ( selectConnectedToDrone )
@@ -58,12 +74,6 @@ export default function Params() {
5874 const fetchingVars = useSelector ( selectFetchingVars )
5975 const fetchingVarsProgress = useSelector ( selectFetchingVarsProgress )
6076
61- function fetchParams ( ) {
62- dispatch ( setFetchingVars ( true ) )
63- dispatch ( emitRefreshParams ( ) )
64- dispatch ( setHasFetchedOnce ( true ) )
65- }
66-
6777 // Reset state if we loose connection
6878 useEffect ( ( ) => {
6979 if ( ! connected ) {
@@ -89,9 +99,68 @@ export default function Params() {
8999 dispatch ( setShownParams ( filteredParams ) )
90100 } , [ debouncedSearchValue , showModifiedParams , params , modifiedParams ] )
91101
102+ function fetchParams ( ) {
103+ dispatch ( setFetchingVars ( true ) )
104+ dispatch ( emitRefreshParams ( ) )
105+ dispatch ( setHasFetchedOnce ( true ) )
106+ }
107+
108+ async function loadParamsFromFile ( ) {
109+ const result = await window . ipcRenderer . invoke (
110+ "params:load-params-from-file" ,
111+ )
112+ if ( ! result ) {
113+ return
114+ }
115+
116+ if ( result . success ) {
117+ dispatch ( setLoadedFileName ( result . name ) )
118+
119+ // Only keep params that are different to the current ones
120+ const loadedParamsList = [ ]
121+ for ( const [ key , value ] of Object . entries ( result . params ) ) {
122+ if ( EXCLUDE_PARAMS_LOAD . includes ( key ) ) {
123+ continue
124+ }
125+
126+ const existingParam = params . find ( ( param ) => param . param_id === key )
127+ const cleanedNewValue = cleanFloat ( value )
128+
129+ if ( existingParam ) {
130+ const cleanedOldValue = cleanFloat ( existingParam . param_value )
131+
132+ if ( cleanedOldValue !== cleanedNewValue ) {
133+ loadedParamsList . push ( {
134+ id : key ,
135+ oldValue : cleanedOldValue ,
136+ newValue : cleanedNewValue ,
137+ type : existingParam . param_type ,
138+ } )
139+ }
140+ } else {
141+ loadedParamsList . push ( {
142+ id : key ,
143+ oldValue : null ,
144+ newValue : cleanedNewValue ,
145+ type : null ,
146+ } )
147+ }
148+ }
149+ dispatch ( setLoadedParams ( loadedParamsList ) )
150+ dispatch ( setLoadParamsFileModalOpen ( true ) )
151+ } else {
152+ showErrorNotification (
153+ `Error loading params from file: ${
154+ result . error || "Please try again."
155+ } `,
156+ )
157+ }
158+ }
159+
92160 return (
93161 < Layout currentPage = "params" >
94162 < AutopilotRebootModal />
163+ < LoadParamsFileModal />
95164
96165 { connected ? (
97166 < >
@@ -112,7 +181,7 @@ export default function Params() {
112181
113182 { Object . keys ( params ) . length > 0 && ! fetchingVars && (
114183 < div className = "w-full h-full contents" >
115- < ParamsToolbar />
184+ < ParamsToolbar loadParamsFromFile = { loadParamsFromFile } />
116185
117186 < div className = "h-full w-2/3 mx-auto" >
118187 < AutoSizer >
0 commit comments