@@ -48,6 +48,7 @@ import {
4848 setLogEvents ,
4949 setFlightModeMessages ,
5050 setLogType ,
51+ setUtcAvailable ,
5152 setMessageFilters ,
5253 setMessageMeans ,
5354 setChartData ,
@@ -127,6 +128,7 @@ export default function FLA() {
127128 logEvents,
128129 flightModeMessages,
129130 logType,
131+ utcAvailable,
130132 messageFilters,
131133 messageMeans,
132134 chartData,
@@ -153,6 +155,8 @@ export default function FLA() {
153155 const updateFlightModeMessages = ( newFlightModeMessages ) =>
154156 dispatch ( setFlightModeMessages ( newFlightModeMessages ) )
155157 const updateLogType = ( newLogType ) => dispatch ( setLogType ( newLogType ) )
158+ const updateUtcAvailable = ( newUtcAvailable ) =>
159+ dispatch ( setUtcAvailable ( newUtcAvailable ) )
156160 const updateMessageFilters = ( newMessageFilters ) =>
157161 dispatch ( setMessageFilters ( newMessageFilters ) )
158162 const updateMessageMeans = ( newMessageMeans ) =>
@@ -177,6 +181,8 @@ export default function FLA() {
177181 setLoadingFile ( true )
178182 const result = await window . ipcRenderer . loadFile ( file . path )
179183
184+ let gpsOffset = null ; // To store the offset between TimeUS and TimeUTC
185+
180186 if ( result . success ) {
181187 // Load messages into states
182188 setLoadingFile ( false )
@@ -198,6 +204,7 @@ export default function FLA() {
198204 if ( result . logType === "dataflash" ) {
199205 updateFlightModeMessages ( loadedLogMessages . MODE )
200206 } else if ( result . logType === "fgcs_telemetry" ) {
207+ updateUtcAvailable ( true )
201208 // Get the heartbeat messages only where index is the first or last or the mode changes
202209 const modeMessages = [ ]
203210 for ( let i = 0 ; i < loadedLogMessages . HEARTBEAT . length ; i ++ ) {
@@ -268,8 +275,33 @@ export default function FLA() {
268275 delete logMessageFilterDefaultState [ "ESC" ]
269276 }
270277
278+ let tempLoadedLogMessages = { ...loadedLogMessages }
279+
280+ if ( "GPS" in loadedLogMessages && result . logType === "dataflash" && gpsOffset === null ) {
281+ const messageObj = tempLoadedLogMessages [ "GPS" ] [ 0 ] // Get the first GPS message
282+
283+ // Calculate the offset
284+ if ( messageObj . GWk !== undefined && messageObj . GMS !== undefined ) {
285+ const utcTime = gpsToUTC ( messageObj . GWk , messageObj . GMS ) ;
286+ gpsOffset = utcTime . getTime ( ) - messageObj . TimeUS / 1000 ;
287+ }
288+
289+ // Loop through all messages and replace TimeUS with UTC
290+ Object . keys ( tempLoadedLogMessages ) . forEach ( ( key ) => {
291+ if ( key !== "format" && key !== "units" ) {
292+ tempLoadedLogMessages [ key ] = tempLoadedLogMessages [ key ] . map ( ( message ) => {
293+ return {
294+ ...message ,
295+ TimeUS : message . TimeUS / 1000 + gpsOffset , // Add the new property
296+ } ;
297+ } ) ;
298+ }
299+ } ) ;
300+ updateUtcAvailable ( true )
301+ updateFlightModeMessages ( tempLoadedLogMessages . MODE )
302+ }
303+
271304 if ( loadedLogMessages [ "BAT" ] ) {
272- let tempLoadedLogMessages = { ...loadedLogMessages }
273305 let tempMsgFormat = { ...loadedLogMessages [ "format" ] }
274306
275307 // Load each BATT data into its own array
@@ -286,6 +318,7 @@ export default function FLA() {
286318 tempLoadedLogMessages [ battName ] . push ( {
287319 ...battData ,
288320 name : battName ,
321+ TimeUS : battData . TimeUS / 1000 + gpsOffset
289322 } )
290323
291324 // Add filter state for new BATT
@@ -344,6 +377,20 @@ export default function FLA() {
344377 }
345378 }
346379
380+ function gpsToUTC ( gpsWeek , gms , leapSeconds = 18 ) {
381+ // GPS epoch starts at 1980-01-06 00:00:00 UTC
382+ const gpsEpoch = new Date ( Date . UTC ( 1980 , 0 , 6 ) ) ;
383+
384+ // Calculate total milliseconds since Unix epoch
385+ const totalMs =
386+ gpsEpoch . getTime ( ) +
387+ gpsWeek * 604_800_000 + // Convert weeks to milliseconds
388+ gms - // Add GPS milliseconds
389+ leapSeconds * 1_000 ; // Subtract leap seconds
390+
391+ return new Date ( totalMs ) ;
392+ }
393+
347394 // Get a list of the recent FGCS telemetry logs
348395 async function getFgcsLogs ( ) {
349396 setRecentFgcsLogs ( await window . ipcRenderer . getRecentLogs ( ) )
@@ -368,6 +415,7 @@ export default function FLA() {
368415 updateChartData ( { datasets : [ ] } )
369416 updateMessageFilters ( null )
370417 updateCustomColors ( { } )
418+ updateUtcAvailable ( false )
371419 updateColorIndex ( 0 )
372420 updateLogEvents ( null )
373421 updateLogType ( "dataflash" )
@@ -880,6 +928,11 @@ export default function FLA() {
880928 ) ,
881929 }
882930
931+ // Skip categories with no valid filters
932+ if ( filteredCategory . filters . length === 0 ) {
933+ return null
934+ }
935+
883936 return (
884937 < Fragment key = { category . name } >
885938 < PresetAccordionItem
@@ -932,7 +985,7 @@ export default function FLA() {
932985 events = { logEvents }
933986 flightModes = { flightModeMessages }
934987 graphConfig = {
935- logType === "dataflash" ? dataflashOptions : fgcsOptions
988+ utcAvailable ? fgcsOptions : dataflashOptions
936989 }
937990 clearFilters = { clearFilters }
938991 canSavePreset = { canSavePreset }
0 commit comments