Skip to content

Commit 063859d

Browse files
authored
Merge branch 'main' into 914-add-force-disarm-modal
2 parents 8adeadc + dd6fee8 commit 063859d

31 files changed

Lines changed: 1196 additions & 106 deletions
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Run Python Copter Tests
2+
3+
permissions:
4+
contents: read
5+
6+
on:
7+
push:
8+
branches:
9+
- main
10+
- release-*
11+
paths:
12+
- radio/**
13+
pull_request:
14+
branches:
15+
- main
16+
- release-*
17+
paths:
18+
- radio/**
19+
20+
jobs:
21+
build:
22+
runs-on: ubuntu-latest
23+
services:
24+
service-name-1:
25+
image: kushmakkapati/ardupilot_sitl:latest
26+
env:
27+
VEHICLE: ArduCopter
28+
ports:
29+
- 5760:5760
30+
options: >-
31+
--name ardupilot-copter
32+
steps:
33+
- uses: actions/checkout@v3
34+
35+
- name: Set up Python 3.11
36+
uses: actions/setup-python@v4
37+
with:
38+
python-version: '3.11'
39+
40+
- name: Install dependencies
41+
working-directory: radio
42+
run: |
43+
python -m pip install --upgrade pip
44+
python -m pip install pytest
45+
python -m pip install -r requirements.txt
46+
47+
- name: Test with pytest
48+
working-directory: radio
49+
timeout-minutes: 15
50+
run: pytest -m "not plane_only" --log-cli-level=DEBUG
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
name: Run Python Tests with simulator
1+
name: Run Python Plane Tests
2+
3+
permissions:
4+
contents: read
25

36
on:
47
push:
@@ -20,8 +23,12 @@ jobs:
2023
services:
2124
service-name-1:
2225
image: kushmakkapati/ardupilot_sitl:latest
26+
env:
27+
VEHICLE: ArduPlane
2328
ports:
2429
- 5760:5760
30+
options: >-
31+
--name ardupilot-plane
2532
steps:
2633
- uses: actions/checkout@v3
2734

@@ -40,4 +47,4 @@ jobs:
4047
- name: Test with pytest
4148
working-directory: radio
4249
timeout-minutes: 15
43-
run: pytest --log-cli-level=DEBUG
50+
run: pytest -m "not copter_only" --log-cli-level=DEBUG

gcs/electron/fla.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,17 @@ function processAndSaveLogData(
485485
} // Save the complete data with required properties
486486
defaultMessageFilters = sortObjectByKeys(finalFilters)
487487

488+
// 7. Get firmware version from VER message if available
489+
let firmwareVersion: string | null = null
490+
if (
491+
loadedLogMessages.VER !== null &&
492+
loadedLogMessages.VER !== undefined &&
493+
Array.isArray(loadedLogMessages.VER) &&
494+
loadedLogMessages.VER.length > 0
495+
) {
496+
firmwareVersion = (loadedLogMessages.VER[0].FWS as string) || null
497+
}
498+
488499
// 8. Return the summary object
489500
return {
490501
formatMessages: finalFormats,
@@ -495,6 +506,7 @@ function processAndSaveLogData(
495506
messageFilters: defaultMessageFilters,
496507
messageMeans: means,
497508
aircraftType,
509+
firmwareVersion,
498510
}
499511
}
500512

gcs/electron/main.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ if (process.platform === "linux") {
5858
let win: BrowserWindow | null
5959
let loadingWin: BrowserWindow | null
6060
let isConnectedToDrone = false
61+
let isArmed = false
62+
let isFlying = false
6163
let quittingApproved = false
6264

6365
// 🚧 Use ['ENV_NAME'] avoid vite:define plugin - Vite@2.x
@@ -141,8 +143,10 @@ ipcMain.handle("settings:save-settings", (_, settings) => {
141143
})
142144

143145
// Cache connection state from renderer
144-
ipcMain.on("app:connected-state", (_event, connected: boolean) => {
145-
isConnectedToDrone = Boolean(connected)
146+
ipcMain.on("app:drone-state", (_event, obj) => {
147+
isConnectedToDrone = Boolean(obj.connectedToDrone)
148+
isArmed = Boolean(obj.isArmed)
149+
isFlying = Boolean(obj.isFlying)
146150
})
147151

148152
ipcMain.handle("app:is-mac", () => {
@@ -451,6 +455,16 @@ app.on("window-all-closed", () => {
451455
closeWithBackend()
452456
})
453457

458+
function getExitMessage() {
459+
if (isFlying) {
460+
return "The aircraft is currently flying."
461+
} else if (isArmed) {
462+
return "The aircraft is currently armed."
463+
} else {
464+
return "You are connected to an aircraft."
465+
}
466+
}
467+
454468
// To ensure that the backend process is killed with Cmd + Q on macOS,
455469
// listen to the before-quit event.
456470
app.on("before-quit", (e) => {
@@ -467,7 +481,7 @@ app.on("before-quit", (e) => {
467481
defaultId: 0,
468482
title: "Confirm Quit",
469483
message: "Are you sure you want to quit FGCS?",
470-
detail: "You are connected to an aircraft.",
484+
detail: getExitMessage(),
471485
})
472486
if (choice === 1) {
473487
quittingApproved = true

gcs/electron/preload.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ const ALLOWED_SEND_CHANNELS = [
4848
"window:zoom-out",
4949
"window:open-file-in-explorer",
5050
"window:update-title",
51-
// app state updates
52-
"app:connected-state",
51+
// drone state updates (connectedToDrone, isArmed, isFlying)
52+
"app:drone-state",
5353
]
5454

5555
const ALLOWED_ON_CHANNELS = [

gcs/electron/types/flaTypes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export interface LogSummary {
9292
{ mean: string; max: string; min: string }
9393
> | null
9494
aircraftType: AircraftType
95+
firmwareVersion: string | null
9596
}
9697

9798
export interface Dataset {

gcs/src/components/config/ftp.jsx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
This is the FTP component for the config page.
3+
4+
It handles all FTP related operations.
5+
*/
6+
// Base imports
7+
8+
// 3rd party imports
9+
10+
// Redux
11+
import { Button, Group, LoadingOverlay, Tree } from "@mantine/core"
12+
import { IconFile, IconFolder, IconFolderOpen } from "@tabler/icons-react"
13+
import { useEffect, useMemo } from "react"
14+
import { useDispatch, useSelector } from "react-redux"
15+
import {
16+
emitListFiles,
17+
resetFiles,
18+
selectFiles,
19+
selectLoadingListFiles,
20+
} from "../../redux/slices/ftpSlice"
21+
22+
export default function Ftp() {
23+
const dispatch = useDispatch()
24+
const files = useSelector(selectFiles)
25+
const loadingListFiles = useSelector(selectLoadingListFiles)
26+
27+
const convertedFiles = useMemo(() => {
28+
if (!files || files.length === 0) return []
29+
return files.map((file) => {
30+
// Need to convert all children recursively
31+
32+
const convertChildren = (children) => {
33+
if (!children) return undefined
34+
return children.map((child) => {
35+
return {
36+
value: child.path,
37+
label: child.name,
38+
children: convertChildren(child.children),
39+
path: child.path,
40+
is_dir: child.is_dir,
41+
}
42+
})
43+
}
44+
45+
return {
46+
value: file.path,
47+
label: file.name,
48+
children: convertChildren(file.children),
49+
path: file.path,
50+
is_dir: file.is_dir,
51+
}
52+
})
53+
}, [files])
54+
55+
useEffect(() => {
56+
if (files.length === 0) {
57+
dispatch(emitListFiles({ path: "/" }))
58+
}
59+
}, [files.length, dispatch])
60+
61+
function handleFileClick(node) {
62+
if (node.is_dir) {
63+
if (node.children === undefined) {
64+
dispatch(emitListFiles({ path: node.path }))
65+
}
66+
}
67+
}
68+
69+
return (
70+
<div className="flex flex-col gap-4 mx-4 relative w-fit">
71+
<LoadingOverlay
72+
visible={loadingListFiles}
73+
zIndex={1000}
74+
overlayProps={{ blur: 2 }}
75+
/>
76+
77+
{loadingListFiles && <p>Loading files...</p>}
78+
79+
<Button
80+
onClick={() => {
81+
dispatch(resetFiles())
82+
}}
83+
w={"fit-content"}
84+
>
85+
Refresh files
86+
</Button>
87+
<Tree
88+
data={convertedFiles}
89+
renderNode={({ node, expanded, elementProps }) => (
90+
<Group gap={5} {...elementProps} key={node.path}>
91+
{node.is_dir ? (
92+
<>
93+
{expanded ? (
94+
<IconFolderOpen size={20} />
95+
) : (
96+
<IconFolder size={20} />
97+
)}
98+
</>
99+
) : (
100+
<IconFile size={20} />
101+
)}
102+
103+
<span
104+
onClick={() => {
105+
handleFileClick(node)
106+
}}
107+
>
108+
{node.label}
109+
</span>
110+
</Group>
111+
)}
112+
/>
113+
</div>
114+
)
115+
}

gcs/src/components/dashboard/tabsSectionTabs/actionTabsSection.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ import {
2222
emitTakeoff,
2323
} from "../../../redux/slices/droneConnectionSlice"
2424
import {
25-
selectArmed,
25+
selectIsArmed,
2626
setLoiterRadius,
2727
} from "../../../redux/slices/droneInfoSlice"
2828

29-
import { NoConnectionMsg } from "../tabsSection"
3029
import { useRebootCallback } from "../../../helpers/droneConnectionCallbacks"
30+
import { NoConnectionMsg } from "../tabsSection"
3131

3232
export default function ActionTabsSection({
3333
connected,
@@ -113,7 +113,7 @@ const ArmTakeoffLandAction = () => {
113113
key: "takeoffAltitude",
114114
defaultValue: 10,
115115
})
116-
const isArmed = useSelector(selectArmed)
116+
const isArmed = useSelector(selectIsArmed)
117117
const rebootCallback = useRebootCallback()
118118

119119
function armDisarm(arm, force = false) {

gcs/src/components/dashboard/telemetrySection/telemetry.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import { useEffect, useState } from "react"
1414
import { useSelector } from "react-redux"
1515
import { intToCoord } from "../../../helpers/dataFormatters"
1616
import {
17-
selectArmed,
1817
selectAttitude,
1918
selectBatteryData,
2019
selectFlightModeString,
2120
selectGPS,
2221
selectHeartbeat,
2322
selectHomePosition,
23+
selectIsArmed,
2424
selectNavController,
2525
selectPrearmEnabled,
2626
selectTelemetry,
@@ -37,7 +37,7 @@ export default function TelemetrySection({
3737
const prearmEnabled = useSelector(selectPrearmEnabled)
3838
const flightMode = useSelector(selectFlightModeString)
3939
const gpsData = useSelector(selectGPS)
40-
const isArmed = useSelector(selectArmed)
40+
const isArmed = useSelector(selectIsArmed)
4141
const telemetryData = useSelector(selectTelemetry)
4242
const attitudeData = useSelector(selectAttitude)
4343
const navControllerOutputData = useSelector(selectNavController)

gcs/src/components/fla/graph.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ export default function Graph({ data, openPresetModal }) {
394394
return (
395395
<div>
396396
<Line ref={chartRef} options={config} data={data} />
397-
<div className="flex flex-row gap-2 pt-2">
397+
<div className="flex flex-row gap-2 py-2">
398398
<MantineTooltip label="Zoom in">
399399
<ActionIcon
400400
variant="filled"

0 commit comments

Comments
 (0)