14 , _commandQueue(commandQueue)
25 for (
auto& compIdEntry : _infoMap) {
26 qDeleteAll(compIdEntry);
30 for (
auto& requestQueue : _queueMap) {
31 qDeleteAll(requestQueue);
36void RequestMessageCoordinator::_noOpResultHandler(
void*, MAV_RESULT, RequestMessageResultHandlerFailureCode_t,
const mavlink_message_t&)
47 const auto repoint = [resultHandlerData](RequestMessageInfo_t* info) {
48 if (info->resultHandlerData == resultHandlerData) {
49 info->resultHandler = &_noOpResultHandler;
50 info->resultHandlerData =
nullptr;
53 for (
auto& msgMap : _infoMap) {
54 for (RequestMessageInfo_t* info : msgMap) {
58 for (
auto& requestQueue : _queueMap) {
59 for (RequestMessageInfo_t* info : requestQueue) {
65bool RequestMessageCoordinator::_duplicate(
int compId,
int msgId)
const
67 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(msgId);
68 const QString msgName = info ? QString(info->name) : QString::number(msgId);
70 if (_infoMap.contains(compId) && _infoMap[compId].contains(msgId)) {
71 qCDebug(RequestMessageCoordinatorLog) <<
"duplicate in active map - compId:msgId" << compId << msgName;
75 if (_queueMap.contains(compId)) {
76 for (
const RequestMessageInfo_t* requestMessageInfo : _queueMap[compId]) {
77 if (requestMessageInfo->msgId == msgId) {
78 qCDebug(RequestMessageCoordinatorLog) <<
"duplicate in queue - compId:msgId" << compId << msgName;
87void RequestMessageCoordinator::_removeInfo(
int compId,
int msgId)
89 if (_infoMap.contains(compId) && _infoMap[compId].contains(msgId)) {
90 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(msgId);
91 const QString msgName = info ? QString(info->name) : QString::
number(msgId);
93 delete _infoMap[compId][msgId];
94 _infoMap[compId].remove(msgId);
95 qCDebug(RequestMessageCoordinatorLog)
96 <<
"removed active request compId:msgId"
100 << _infoMap[compId].count();
101 if (_infoMap[compId].isEmpty()) {
102 _infoMap.remove(compId);
104 _sendNextFromQueue(compId);
106 qWarning() <<
"compId:msgId not found" << compId << msgId;
110void RequestMessageCoordinator::_sendNow(RequestMessageInfo_t* info)
112 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
113 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::
number(info->msgId);
115 _infoMap[info->compId][info->msgId] = info;
117 const int queueDepth = _queueMap.contains(info->compId) ? _queueMap[info->compId].count() : 0;
118 qCDebug(RequestMessageCoordinatorLog)
119 <<
"sending now compId:msgId"
127 handlerInfo.resultHandlerData = info;
133 MAV_CMD_REQUEST_MESSAGE,
144void RequestMessageCoordinator::_sendNextFromQueue(
int compId)
146 if (_infoMap.contains(compId) && !_infoMap[compId].isEmpty()) {
147 qCDebug(RequestMessageCoordinatorLog)
148 <<
"active request still in progress for compId"
151 << _infoMap[compId].count();
155 if (!_queueMap.contains(compId) || _queueMap[compId].isEmpty()) {
156 qCDebug(RequestMessageCoordinatorLog) <<
"no queued request for compId" << compId;
157 _queueMap.remove(compId);
161 RequestMessageInfo_t* info = _queueMap[compId].takeFirst();
162 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
163 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::
number(info->msgId);
164 const int remainingQueue = _queueMap[compId].count();
165 qCDebug(RequestMessageCoordinatorLog)
166 <<
"dequeued next request compId:msgId"
172 if (_queueMap[compId].isEmpty()) {
173 _queueMap.remove(compId);
181 if (_infoMap.contains(message.compid) && _infoMap[message.compid].contains(message.msgid)) {
182 auto pInfo = _infoMap[message.compid][message.msgid];
183 auto resultHandler = pInfo->resultHandler;
184 auto resultHandlerData = pInfo->resultHandlerData;
188 if (message.msgid == MAVLINK_MSG_ID_AVAILABLE_MODES) {
189 const uint8_t requestedModeIndex =
static_cast<uint8_t
>(pInfo->param1);
190 const uint8_t receivedModeIndex = mavlink_msg_available_modes_get_mode_index(&message);
191 if (requestedModeIndex != 0 && receivedModeIndex != requestedModeIndex) {
192 qCDebug(RequestMessageCoordinatorLog)
193 <<
"ignoring AVAILABLE_MODES for other mode - received:" << receivedModeIndex
194 <<
"requested:" << requestedModeIndex;
199 pInfo->messageReceived =
true;
200 pInfo->message = message;
202 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(message.msgid);
203 QString msgName = info ? QString(info->name) : QString::number(message.msgid);
204 const int activeCount = _infoMap.contains(message.compid) ? _infoMap[message.compid].count() : 0;
205 const int queueDepth = _queueMap.contains(message.compid) ? _queueMap[message.compid].count() : 0;
206 qCDebug(RequestMessageCoordinatorLog)
207 <<
"message received - compId:msgId"
215 if (pInfo->commandAckReceived) {
216 _removeInfo(message.compid, message.msgid);
224 int timedOutCompId = -1;
225 int timedOutMsgId = -1;
227 void* timedOutHandlerData =
nullptr;
228 for (
auto& compIdEntry : _infoMap) {
229 for (
auto info : compIdEntry) {
232 if (info->messageWaitElapsedTimer.isValid() && info->messageWaitElapsedTimer.elapsed() > messageWaitTimeoutMs) {
233 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
234 QString msgName = msgInfo ? msgInfo->name : QString::number(info->msgId);
235 const int queueDepth = _queueMap.contains(info->compId) ? _queueMap[info->compId].count() : 0;
236 qCDebug(RequestMessageCoordinatorLog)
237 <<
"request message timed out - compId:msgId"
243 timedOutCompId = info->compId;
244 timedOutMsgId = info->msgId;
245 timedOutHandler = info->resultHandler;
246 timedOutHandlerData = info->resultHandlerData;
250 if (timedOutHandler) {
255 if (timedOutHandler) {
256 _removeInfo(timedOutCompId, timedOutMsgId);
262void RequestMessageCoordinator::_cmdResultHandler(
void* resultHandlerData_, [[maybe_unused]]
int compId,
const mavlink_command_ack_t& ack, MavCmdResultFailureCode_t failureCode)
264 auto info =
static_cast<RequestMessageInfo_t*
>(resultHandlerData_);
265 auto resultHandler = info->resultHandler;
266 auto resultHandlerData = info->resultHandlerData;
267 Vehicle* vehicle = info->vehicle;
271 qCDebug(RequestMessageCoordinatorLog) <<
"Vehicle destroyed before callback - skipping";
276 auto* coordinator = info->coordinator;
278 info->commandAckReceived =
true;
279 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(info->msgId);
280 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::
number(info->msgId);
281 qCDebug(RequestMessageCoordinatorLog)
282 <<
"ack for requestMessage compId:msgId"
290 if (ack.result != MAV_RESULT_ACCEPTED) {
294 switch (failureCode) {
306 coordinator->_removeInfo(info->compId, info->msgId);
307 (*resultHandler)(resultHandlerData,
static_cast<MAV_RESULT
>(ack.result), requestMessageFailureCode, ackMessage);
311 if (info->messageReceived) {
312 auto message = info->message;
313 coordinator->_removeInfo(info->compId, info->msgId);
319 info->messageWaitElapsedTimer.start();
324 const mavlink_message_info_t* msgInfo = mavlink_get_message_info_by_id(messageId);
325 const QString msgName = msgInfo ? QString(msgInfo->name) : QString::number(messageId);
326 const int activeCount = _infoMap.contains(compId) ? _infoMap[compId].count() : 0;
327 const int queueDepth = _queueMap.contains(compId) ? _queueMap[compId].count() : 0;
328 qCDebug(RequestMessageCoordinatorLog)
329 <<
"incoming request compId:msgId"
337 auto info =
new RequestMessageInfo_t;
338 info->vehicle = _vehicle;
339 info->coordinator =
this;
341 info->msgId = messageId;
342 info->param1 = param1;
343 info->param2 = param2;
344 info->param3 = param3;
345 info->param4 = param4;
346 info->param5 = param5;
347 info->resultHandler = resultHandler;
348 info->resultHandlerData = resultHandlerData;
350 if (_duplicate(compId, messageId)) {
352 qCWarning(RequestMessageCoordinatorLog) <<
"failing exact duplicate compId:msgId" << compId << msgName;
353 (*resultHandler)(resultHandlerData,
361 if (_infoMap.contains(compId) && !_infoMap[compId].isEmpty()) {
362 _queueMap[compId].append(info);
363 qCDebug(RequestMessageCoordinatorLog)
364 <<
"queued request compId:msgId"
368 << _queueMap[compId].count();
377 switch (failureCode) {
379 return QStringLiteral(
"No Failure");
381 return QStringLiteral(
"Command Error");
383 return QStringLiteral(
"Command Not Acked");
385 return QStringLiteral(
"Message Not Received");
387 return QStringLiteral(
"Duplicate Request");
389 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
Owns the COMMAND_LONG / COMMAND_INT send/retry/ack pipeline for a single Vehicle.
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)
Coordinates MAV_CMD_REQUEST_MESSAGE workflows: per-component queueing, ack/message correlation,...
void handleReceivedMessage(const mavlink_message_t &message)
void cancelRequests(void *resultHandlerData)
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).
std::optional< T > number(std::string_view field, int base=DECIMAL_BASE)
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