14 , _commandQueue(commandQueue)
25 for (
auto& compIdEntry : _infoMap) {
26 qDeleteAll(compIdEntry);
30 for (
auto& requestQueue : _queueMap) {
31 qDeleteAll(requestQueue);
36bool RequestMessageCoordinator::_duplicate(
int compId,
int msgId)
const
38 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(msgId);
39 const QString msgName = info ? QString(info->name) : QString::number(msgId);
41 if (_infoMap.contains(compId) && _infoMap[compId].contains(msgId)) {
42 qCDebug(RequestMessageCoordinatorLog) <<
"duplicate in active map - compId:msgId" << compId << msgName;
46 if (_queueMap.contains(compId)) {
47 for (
const RequestMessageInfo_t* requestMessageInfo : _queueMap[compId]) {
48 if (requestMessageInfo->msgId == msgId) {
49 qCDebug(RequestMessageCoordinatorLog) <<
"duplicate in queue - compId:msgId" << compId << msgName;
58void RequestMessageCoordinator::_removeInfo(
int compId,
int msgId)
60 if (_infoMap.contains(compId) && _infoMap[compId].contains(msgId)) {
61 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(msgId);
62 const QString msgName = info ? QString(info->name) : QString::number(msgId);
64 delete _infoMap[compId][msgId];
65 _infoMap[compId].remove(msgId);
66 qCDebug(RequestMessageCoordinatorLog)
67 <<
"removed active request compId:msgId"
71 << _infoMap[compId].count();
72 if (_infoMap[compId].isEmpty()) {
73 _infoMap.remove(compId);
75 _sendNextFromQueue(compId);
77 qWarning() <<
"compId:msgId not found" << compId << msgId;
81void RequestMessageCoordinator::_sendNow(RequestMessageInfo_t* info)
83 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
84 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::number(info->msgId);
86 _infoMap[info->compId][info->msgId] = info;
88 const int queueDepth = _queueMap.contains(info->compId) ? _queueMap[info->compId].count() : 0;
89 qCDebug(RequestMessageCoordinatorLog)
90 <<
"sending now compId:msgId"
98 handlerInfo.resultHandlerData = info;
104 MAV_CMD_REQUEST_MESSAGE,
115void RequestMessageCoordinator::_sendNextFromQueue(
int compId)
117 if (_infoMap.contains(compId) && !_infoMap[compId].isEmpty()) {
118 qCDebug(RequestMessageCoordinatorLog)
119 <<
"active request still in progress for compId"
122 << _infoMap[compId].count();
126 if (!_queueMap.contains(compId) || _queueMap[compId].isEmpty()) {
127 qCDebug(RequestMessageCoordinatorLog) <<
"no queued request for compId" << compId;
128 _queueMap.remove(compId);
132 RequestMessageInfo_t* info = _queueMap[compId].takeFirst();
133 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
134 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::number(info->msgId);
135 const int remainingQueue = _queueMap[compId].count();
136 qCDebug(RequestMessageCoordinatorLog)
137 <<
"dequeued next request compId:msgId"
143 if (_queueMap[compId].isEmpty()) {
144 _queueMap.remove(compId);
152 if (_infoMap.contains(message.compid) && _infoMap[message.compid].contains(message.msgid)) {
153 auto pInfo = _infoMap[message.compid][message.msgid];
154 auto resultHandler = pInfo->resultHandler;
155 auto resultHandlerData = pInfo->resultHandlerData;
157 pInfo->messageReceived =
true;
158 pInfo->message = message;
160 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(message.msgid);
161 QString msgName = info ? QString(info->name) : QString::number(message.msgid);
162 const int activeCount = _infoMap.contains(message.compid) ? _infoMap[message.compid].count() : 0;
163 const int queueDepth = _queueMap.contains(message.compid) ? _queueMap[message.compid].count() : 0;
164 qCDebug(RequestMessageCoordinatorLog)
165 <<
"message received - compId:msgId"
173 if (pInfo->commandAckReceived) {
174 _removeInfo(message.compid, message.msgid);
182 int timedOutCompId = -1;
183 int timedOutMsgId = -1;
185 void* timedOutHandlerData =
nullptr;
186 for (
auto& compIdEntry : _infoMap) {
187 for (
auto info : compIdEntry) {
191 if (info->messageWaitElapsedTimer.isValid() && info->messageWaitElapsedTimer.elapsed() > messageWaitTimeoutMs) {
192 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
193 QString msgName = msgInfo ? msgInfo->name : QString::number(info->msgId);
194 const int queueDepth = _queueMap.contains(info->compId) ? _queueMap[info->compId].count() : 0;
195 qCDebug(RequestMessageCoordinatorLog)
196 <<
"request message timed out - compId:msgId"
202 timedOutCompId = info->compId;
203 timedOutMsgId = info->msgId;
204 timedOutHandler = info->resultHandler;
205 timedOutHandlerData = info->resultHandlerData;
209 if (timedOutHandler) {
214 if (timedOutHandler) {
215 _removeInfo(timedOutCompId, timedOutMsgId);
221void RequestMessageCoordinator::_cmdResultHandler(
void* resultHandlerData_, [[maybe_unused]]
int compId,
const mavlink_command_ack_t& ack, MavCmdResultFailureCode_t failureCode)
223 auto info =
static_cast<RequestMessageInfo_t*
>(resultHandlerData_);
224 auto resultHandler = info->resultHandler;
225 auto resultHandlerData = info->resultHandlerData;
226 Vehicle* vehicle = info->vehicle;
230 qCDebug(RequestMessageCoordinatorLog) <<
"Vehicle destroyed before callback - skipping";
235 auto* coordinator = info->coordinator;
237 info->commandAckReceived =
true;
238 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
239 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::number(info->msgId);
240 qCDebug(RequestMessageCoordinatorLog)
241 <<
"ack for requestMessage compId:msgId"
249 if (ack.result != MAV_RESULT_ACCEPTED) {
253 switch (failureCode) {
265 coordinator->_removeInfo(info->compId, info->msgId);
266 (*resultHandler)(resultHandlerData,
static_cast<MAV_RESULT
>(ack.result), requestMessageFailureCode, ackMessage);
270 if (info->messageReceived) {
271 auto message = info->message;
272 coordinator->_removeInfo(info->compId, info->msgId);
278 info->messageWaitElapsedTimer.start();
283 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(messageId);
284 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::number(messageId);
285 const int activeCount = _infoMap.contains(compId) ? _infoMap[compId].count() : 0;
286 const int queueDepth = _queueMap.contains(compId) ? _queueMap[compId].count() : 0;
287 qCDebug(RequestMessageCoordinatorLog)
288 <<
"incoming request compId:msgId"
296 auto info =
new RequestMessageInfo_t;
297 info->vehicle = _vehicle;
298 info->coordinator =
this;
300 info->msgId = messageId;
301 info->param1 = param1;
302 info->param2 = param2;
303 info->param3 = param3;
304 info->param4 = param4;
305 info->param5 = param5;
306 info->resultHandler = resultHandler;
307 info->resultHandlerData = resultHandlerData;
309 if (_duplicate(compId, messageId)) {
311 qCWarning(RequestMessageCoordinatorLog) <<
"failing exact duplicate compId:msgId" << compId << msgName;
312 (*resultHandler)(resultHandlerData,
320 if (_infoMap.contains(compId) && !_infoMap[compId].isEmpty()) {
321 _queueMap[compId].append(info);
322 qCDebug(RequestMessageCoordinatorLog)
323 <<
"queued request compId:msgId"
327 << _queueMap[compId].count();
336 switch (failureCode) {
338 return QStringLiteral(
"No Failure");
340 return QStringLiteral(
"Command Error");
342 return QStringLiteral(
"Command Not Acked");
344 return QStringLiteral(
"Message Not Received");
346 return QStringLiteral(
"Duplicate Request");
348 return QStringLiteral(
"Unknown (%1)").arg(failureCode);
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct __mavlink_command_ack_t mavlink_command_ack_t
static QString failureCodeToString(MavCmdResultFailureCode_t failureCode)
void sendWorker(bool commandInt, bool showError, const MavCmdAckHandlerInfo_t *ackHandlerInfo, int compId, MAV_CMD command, MAV_FRAME frame, float param1, float param2, float param3, float param4, double param5, double param6, float param7)
static QString mavResultToString(uint8_t result)
void handleReceivedMessage(const mavlink_message_t &message)
static QString failureCodeToString(RequestMessageResultHandlerFailureCode_t failureCode)
~RequestMessageCoordinator()
void requestMessage(RequestMessageResultHandler resultHandler, void *resultHandlerData, int compId, int messageId, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, float param5=0.0f)
void stop()
Clear pending state without firing callbacks (used during vehicle shutdown).
bool runningUnitTests()
True if the app is running in unit-test mode. Returns false if qgcApp() doesn't exist yet.
MavCmdResultHandler resultHandler
nullptr for no handler
void(* RequestMessageResultHandler)(void *resultHandlerData, MAV_RESULT commandResult, RequestMessageResultHandlerFailureCode_t failureCode, const mavlink_message_t &message)
Callback for requestMessage — delivered when the ack/message pair resolves or a failure occurs.
struct VehicleTypes::MavCmdAckHandlerInfo_s MavCmdAckHandlerInfo_t
Callback info bundle for sendMavCommandWithHandler.
@ MavCmdResultFailureDuplicateCommand
Unable to send command since duplicate is already being waited on for response.
@ MavCmdResultCommandResultOnly
commandResult specifies full success/fail info
@ MavCmdResultFailureNoResponseToCommand
No response from vehicle to command.
RequestMessageResultHandlerFailureCode_t
@ RequestMessageFailureMessageNotReceived
@ RequestMessageFailureCommandNotAcked
@ RequestMessageFailureDuplicate
Exact duplicate request already active or queued for this component/message id.
@ RequestMessageFailureCommandError
@ RequestMessageNoFailure