|
1 | 1 | import sys |
2 | 2 | import time |
| 3 | +from threading import Event |
3 | 4 | from typing import Optional |
4 | 5 |
|
5 | 6 | from serial.tools import list_ports |
|
11 | 12 | from app.utils import ( |
12 | 13 | droneConnectStatusCb, |
13 | 14 | droneErrorCb, |
| 15 | + fetchingParameterCb, |
14 | 16 | getComPortNames, |
15 | 17 | getFlightSwVersionString, |
16 | | - fetchingParameterCb, |
17 | 18 | ) |
18 | 19 |
|
19 | 20 |
|
@@ -78,13 +79,6 @@ def connectToDrone(data: ConnectionDataType) -> None: |
78 | 79 | Args: |
79 | 80 | data: The message passed in from the client containing the form sent (select com port, baud rate) |
80 | 81 | """ |
81 | | - if droneStatus.drone: |
82 | | - droneStatus.drone.logger.warning( |
83 | | - "Attempting a connection to drone when connection is already established." |
84 | | - ) |
85 | | - droneStatus.drone.close() |
86 | | - droneStatus.drone = None |
87 | | - |
88 | 82 | connectionType = data.get("connectionType") |
89 | 83 |
|
90 | 84 | if connectionType not in ["serial", "network"]: |
@@ -133,45 +127,100 @@ def connectToDrone(data: ConnectionDataType) -> None: |
133 | 127 | droneStatus.drone = None |
134 | 128 | return |
135 | 129 |
|
136 | | - drone = Drone( |
137 | | - port, |
138 | | - baud=baud, |
139 | | - forwarding_address=forwarding_address, |
140 | | - droneErrorCb=droneErrorCb, |
141 | | - droneDisconnectCb=disconnectFromDrone, |
142 | | - droneConnectStatusCb=droneConnectStatusCb, |
143 | | - linkDebugStatsCb=sendLinkDebugStats, |
144 | | - fetchingParameterCb=fetchingParameterCb, |
145 | | - ) |
146 | | - |
147 | | - if drone.connectionError is not None: |
148 | | - socketio.emit("connection_error", {"message": drone.connectionError}) |
149 | | - droneStatus.drone = None |
150 | | - return |
| 130 | + old_drone = None |
| 131 | + with droneStatus.connection_state_lock: |
| 132 | + if droneStatus.connection_in_progress: |
| 133 | + socketio.emit( |
| 134 | + "connection_error", |
| 135 | + {"message": "A drone connection is already in progress."}, |
| 136 | + ) |
| 137 | + return |
151 | 138 |
|
152 | | - # Set droneStatus drone to local drone |
153 | | - droneStatus.drone = drone |
| 139 | + if droneStatus.drone: |
| 140 | + old_drone = droneStatus.drone |
| 141 | + droneStatus.drone = None |
154 | 142 |
|
155 | | - # Sleeping for buffer time, if errors occur try changing back to 1 second |
156 | | - time.sleep(0.2) |
157 | | - logger.debug("Created drone instance") |
158 | | - socketio.emit( |
159 | | - "connected_to_drone", |
160 | | - { |
161 | | - "aircraft_type": drone.aircraft_type, |
162 | | - "flight_sw_version": getFlightSwVersionString(drone.flight_sw_version), |
163 | | - }, |
164 | | - ) |
| 143 | + cancel_event = Event() |
| 144 | + droneStatus.connect_cancel_event = cancel_event |
| 145 | + droneStatus.connection_in_progress = True |
| 146 | + |
| 147 | + if old_drone is not None: |
| 148 | + old_drone.logger.warning( |
| 149 | + "Attempting a connection to drone when connection is already established." |
| 150 | + ) |
| 151 | + old_drone.close() |
| 152 | + |
| 153 | + try: |
| 154 | + drone = Drone( |
| 155 | + port, |
| 156 | + baud=baud, |
| 157 | + forwarding_address=forwarding_address, |
| 158 | + droneErrorCb=droneErrorCb, |
| 159 | + droneDisconnectCb=disconnectFromDrone, |
| 160 | + droneConnectStatusCb=droneConnectStatusCb, |
| 161 | + linkDebugStatsCb=sendLinkDebugStats, |
| 162 | + fetchingParameterCb=fetchingParameterCb, |
| 163 | + connectionCancelEvent=cancel_event, |
| 164 | + ) |
| 165 | + |
| 166 | + if drone.connectionError is not None: |
| 167 | + socketio.emit("connection_error", {"message": drone.connectionError}) |
| 168 | + droneStatus.drone = None |
| 169 | + return |
| 170 | + |
| 171 | + # Set droneStatus drone to local drone |
| 172 | + droneStatus.drone = drone |
| 173 | + |
| 174 | + # Sleeping for buffer time, if errors occur try changing back to 1 second |
| 175 | + time.sleep(0.2) |
| 176 | + logger.debug("Created drone instance") |
| 177 | + socketio.emit( |
| 178 | + "connected_to_drone", |
| 179 | + { |
| 180 | + "aircraft_type": drone.aircraft_type, |
| 181 | + "flight_sw_version": getFlightSwVersionString(drone.flight_sw_version), |
| 182 | + }, |
| 183 | + ) |
| 184 | + finally: |
| 185 | + with droneStatus.connection_state_lock: |
| 186 | + droneStatus.connection_in_progress = False |
| 187 | + droneStatus.connect_cancel_event = None |
| 188 | + |
| 189 | + |
| 190 | +@socketio.on("cancel_connect_to_drone") |
| 191 | +def cancelConnectToDrone() -> None: |
| 192 | + """Cancel an in-progress drone connection attempt.""" |
| 193 | + with droneStatus.connection_state_lock: |
| 194 | + if droneStatus.connection_in_progress and droneStatus.connect_cancel_event: |
| 195 | + logger.info("Connection cancel requested by user") |
| 196 | + droneStatus.connect_cancel_event.set() |
| 197 | + else: |
| 198 | + logger.debug( |
| 199 | + "Connection cancel requested, but no connection is in progress" |
| 200 | + ) |
165 | 201 |
|
166 | 202 |
|
167 | 203 | @socketio.on("disconnect_from_drone") |
168 | 204 | def disconnectFromDrone() -> None: |
169 | 205 | """ |
170 | 206 | Disconnect from drone and reset all global variables, send a message to client disconnecting as well |
171 | 207 | """ |
172 | | - if droneStatus.drone: |
173 | | - droneStatus.drone.close() |
174 | | - droneStatus.drone = None |
| 208 | + with droneStatus.connection_state_lock: |
| 209 | + if droneStatus.drone: |
| 210 | + drone = droneStatus.drone |
| 211 | + droneStatus.drone = None |
| 212 | + else: |
| 213 | + drone = None |
| 214 | + |
| 215 | + if ( |
| 216 | + drone is None |
| 217 | + and droneStatus.connection_in_progress |
| 218 | + and droneStatus.connect_cancel_event |
| 219 | + ): |
| 220 | + droneStatus.connect_cancel_event.set() |
| 221 | + |
| 222 | + if drone is not None: |
| 223 | + drone.close() |
175 | 224 |
|
176 | 225 | droneStatus.state = None |
177 | 226 | socketio.emit("disconnected_from_drone") |
0 commit comments