diff --git a/core/frontend/src/components/autopilot/EndpointManager.vue b/core/frontend/src/components/autopilot/EndpointManager.vue index 9a4af9f5e7..0e42430c75 100644 --- a/core/frontend/src/components/autopilot/EndpointManager.vue +++ b/core/frontend/src/components/autopilot/EndpointManager.vue @@ -65,14 +65,36 @@ subtitle="Fetching available endpoints..." /> - -

- No endpoints available. -

-
+ +
+

+ Autopilot must be running to create endpoints. +

+

+ You can start it in the + + Autopilot Firmware + + tab. +

+
+
+ +

+ No endpoints available. +

+
+ mdi-plus @@ -103,13 +126,14 @@ import Vue from 'vue' import Notifier from '@/libs/notifier' import { OneMoreTime } from '@/one-more-time' +import autopilot_data from '@/store/autopilot' import autopilot from '@/store/autopilot_manager' import { AutopilotEndpoint } from '@/types/autopilot' import { autopilot_service } from '@/types/frontend_services' import back_axios from '@/utils/api' import SpinningLogo from '../common/SpinningLogo.vue' -import { fetchAvailableEndpoints } from './AutopilotManagerUpdater' +import { fetchAvailableEndpoints, fetchCurrentBoard } from './AutopilotManagerUpdater' import EndpointCard from './EndpointCard.vue' import CreationDialog from './EndpointCreationDialog.vue' @@ -128,7 +152,10 @@ export default Vue.extend({ selected_router: '', available_routers: [] as string[], updating_router: false, + heartbeat_expired: false, + heartbeat_timeout: null as number | null, fetch_available_endpoints_task: new OneMoreTime({ delay: 5000, disposeWith: this }), + fetch_current_board_task: new OneMoreTime({ delay: 5000, disposeWith: this }), } }, computed: { @@ -141,9 +168,29 @@ export default Vue.extend({ are_endpoints_available(): boolean { return !this.available_endpoints.isEmpty() }, + autopilot_board_is_running(): boolean { + return autopilot.current_board !== null && !this.heartbeat_expired && this.heartbeat_age() < 3000 + }, + }, + watch: { + 'autopilot_data.last_heartbeat_date': function onHeartbeatDateChange() { + if (this.heartbeat_timeout) { + clearTimeout(this.heartbeat_timeout) + } + this.heartbeat_expired = false + this.heartbeat_timeout = setTimeout(() => { + this.heartbeat_expired = true + }, 3000) + }, + }, + beforeDestroy() { + if (this.heartbeat_timeout) { + clearTimeout(this.heartbeat_timeout) + } }, mounted() { this.fetch_available_endpoints_task.setAction(fetchAvailableEndpoints) + this.fetch_current_board_task.setAction(fetchCurrentBoard) this.fetchAvailableRouters() this.fetchCurrentRouter() }, @@ -206,6 +253,9 @@ export default Vue.extend({ notifier.pushBackError('AUTOPILOT_ENDPOINT_CREATE_FAIL', error, true) }) }, + heartbeat_age(): number { + return new Date().valueOf() - autopilot_data.last_heartbeat_date.getTime() + }, }, }) diff --git a/core/frontend/src/components/health/HealthTrayMenu.vue b/core/frontend/src/components/health/HealthTrayMenu.vue index cce1cff5cb..1a4c669c3b 100644 --- a/core/frontend/src/components/health/HealthTrayMenu.vue +++ b/core/frontend/src/components/health/HealthTrayMenu.vue @@ -170,7 +170,6 @@ export default Vue.extend({ data() { return { time_limit_heartbeat: 3000, - last_heartbeat_date: new Date(), } }, computed: { @@ -238,12 +237,12 @@ export default Vue.extend({ autopilot_data.setSystemId(message?.header.system_id) autopilot_data.setAutopilotType(message?.message.autopilot.type) autopilot_data.setVehicleArmed(Boolean(message?.message.base_mode.bits & MavModeFlag.MAV_MODE_FLAG_SAFETY_ARMED)) - this.last_heartbeat_date = new Date() + autopilot_data.setLastHeartbeatDate(new Date()) }).setFrequency(0) }, methods: { heartbeat_age(): number { - return new Date().valueOf() - this.last_heartbeat_date.getTime() + return new Date().valueOf() - autopilot_data.last_heartbeat_date.getTime() }, is_vehicle(type: string) { return [ diff --git a/core/frontend/src/store/autopilot.ts b/core/frontend/src/store/autopilot.ts index e890f01ec1..ec9522e36e 100644 --- a/core/frontend/src/store/autopilot.ts +++ b/core/frontend/src/store/autopilot.ts @@ -55,6 +55,8 @@ class AutopilotStore extends VuexModule { verhicle_armed = false + last_heartbeat_date: Date = new Date() + get parameter() { return (name: string): Parameter | undefined => this.parameters.find((parameter) => parameter.name === name) } @@ -72,7 +74,6 @@ class AutopilotStore extends VuexModule { ) } - get vehicle_type(): string { return autopilot_manager.vehicle_type } @@ -173,6 +174,11 @@ class AutopilotStore extends VuexModule { setVehicleArmed(armed: boolean): void { this.verhicle_armed = armed } + + @Mutation + setLastHeartbeatDate(date: Date): void { + this.last_heartbeat_date = date + } } export { AutopilotStore } diff --git a/core/frontend/src/views/Autopilot.vue b/core/frontend/src/views/Autopilot.vue index a02c0eb5d8..343338e216 100644 --- a/core/frontend/src/views/Autopilot.vue +++ b/core/frontend/src/views/Autopilot.vue @@ -88,7 +88,7 @@ Change board