QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
MessageIntervalManager.cc
Go to the documentation of this file.
2
3#include <memory>
4
5#include <QtCore/QPointer>
6
7#include "MavCommandQueue.h"
8#include "MAVLinkLib.h"
11#include "Vehicle.h"
12
13QGC_LOGGING_CATEGORY(MessageIntervalManagerLog, "Vehicle.MessageIntervalManager")
14
15namespace {
16
17// Per-request heap state — concurrent requests must not share a single msgId slot.
18struct RequestIntervalData {
19 QPointer<MessageIntervalManager> manager;
20 uint8_t compId;
21 uint16_t msgId;
22};
23
24struct SetRateData {
25 QPointer<MessageIntervalManager> manager;
26 uint8_t compId;
27 uint16_t msgId;
28};
29
30} // namespace
31
33 : QObject(vehicle)
34 , _vehicle(vehicle)
35 , _commandQueue(commandQueue)
36 , _reqMsgCoord(reqMsgCoord)
37{
38}
39
41{
42 mavlink_message_interval_t data;
43 mavlink_msg_message_interval_decode(&message, &data);
44
45 const MavCompMsgId compMsgId = {message.compid, data.message_id};
46 const int32_t rate = (data.interval_us > 0) ? 1000000.0 / data.interval_us : data.interval_us;
47
48 if (!_mavlinkMsgIntervals.contains(compMsgId) || _mavlinkMsgIntervals.value(compMsgId) != rate) {
49 (void) _mavlinkMsgIntervals.insert(compMsgId, rate);
50 emit mavlinkMsgIntervalsChanged(message.compid, data.message_id, rate);
51 }
52}
53
54void MessageIntervalManager::_requestMessageIntervalResultHandler(void* resultHandlerData, MAV_RESULT result, RequestMessageResultHandlerFailureCode_t failureCode, const mavlink_message_t& /*message*/)
55{
56 // `message` is indeterminate on failure paths — use the tracked msgId instead of decoding.
57 std::unique_ptr<RequestIntervalData> ctx(static_cast<RequestIntervalData*>(resultHandlerData));
58 if (!ctx || !ctx->manager) {
59 return;
60 }
61
62 if ((result != MAV_RESULT_ACCEPTED) || (failureCode != RequestMessageNoFailure)) {
63 (void) ctx->manager->_unsupportedMessageIds.insert(ctx->compId, ctx->msgId);
64 }
65}
66
67void MessageIntervalManager::_requestMessageInterval(uint8_t compId, uint16_t msgId)
68{
69 if (_unsupportedMessageIds.contains(compId, msgId)) {
70 return;
71 }
72
73 auto* ctx = new RequestIntervalData{this, compId, msgId};
74 _reqMsgCoord->requestMessage(
75 &MessageIntervalManager::_requestMessageIntervalResultHandler,
76 ctx,
77 compId,
78 MAVLINK_MSG_ID_MESSAGE_INTERVAL,
79 msgId);
80}
81
82int32_t MessageIntervalManager::getMessageRate(uint8_t compId, uint16_t msgId)
83{
84 // TODO: Use QGCMavlinkMessage
85 const MavCompMsgId compMsgId = {compId, msgId};
86 int32_t rate = 0;
87 if (_mavlinkMsgIntervals.contains(compMsgId)) {
88 rate = _mavlinkMsgIntervals.value(compMsgId);
89 } else {
90 _requestMessageInterval(compId, msgId);
91 }
92 return rate;
93}
94
95void MessageIntervalManager::_setMessageRateCommandResultHandler(void* resultHandlerData, int /*compId*/, const mavlink_command_ack_t& ack, MavCmdResultFailureCode_t failureCode)
96{
97 std::unique_ptr<SetRateData> ctx(static_cast<SetRateData*>(resultHandlerData));
98 if (!ctx || !ctx->manager) {
99 return;
100 }
101
102 if ((ack.result == MAV_RESULT_ACCEPTED) && (failureCode == MavCmdResultCommandResultOnly)) {
103 ctx->manager->_requestMessageInterval(ctx->compId, ctx->msgId);
104 }
105}
106
107void MessageIntervalManager::setMessageRate(uint8_t compId, uint16_t msgId, int32_t rate)
108{
109 auto* ctx = new SetRateData{this, compId, msgId};
110 const MavCmdAckHandlerInfo_t handlerInfo = {
111 /* .resultHandler = */ &MessageIntervalManager::_setMessageRateCommandResultHandler,
112 /* .resultHandlerData = */ ctx,
113 /* .progressHandler = */ nullptr,
114 /* .progressHandlerData = */ nullptr,
115 };
116
117 const float interval = (rate > 0) ? 1000000.0 / rate : rate;
118
119 _commandQueue->sendCommandWithHandler(
120 &handlerInfo,
121 compId,
122 MAV_CMD_SET_MESSAGE_INTERVAL,
123 static_cast<float>(msgId),
124 interval);
125}
126
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct __mavlink_command_ack_t mavlink_command_ack_t
void sendCommandWithHandler(const MavCmdAckHandlerInfo_t *ackHandlerInfo, int compId, MAV_CMD command, float param1=0.0f, float param2=0.0f, float param3=0.0f, float param4=0.0f, float param5=0.0f, float param6=0.0f, float param7=0.0f)
void handleMessageInterval(const mavlink_message_t &message)
void mavlinkMsgIntervalsChanged(uint8_t compid, uint16_t msgId, int32_t rate)
void setMessageRate(uint8_t compId, uint16_t msgId, int32_t rate)
MessageIntervalManager(Vehicle *vehicle, MavCommandQueue *commandQueue, RequestMessageCoordinator *reqMsgCoord)
int32_t getMessageRate(uint8_t compId, uint16_t msgId)
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)
Callback info bundle for sendMavCommandWithHandler.
@ MavCmdResultCommandResultOnly
commandResult specifies full success/fail info
@ RequestMessageNoFailure