QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
QGCCameraIO.cc
Go to the documentation of this file.
1#include "QGCCameraIO.h"
3#include "LinkInterface.h"
4#include "MAVLinkProtocol.h"
6#include "Vehicle.h"
7
8QGC_LOGGING_CATEGORY(QGCCameraParamIOLog, "Camera.QGCCameraParamIO")
9QGC_LOGGING_CATEGORY(QGCCameraParamIOVerbose, "Camera.QGCCameraParamIO:verbose")
10
11namespace {
12 constexpr int kMaxRetries = 3;
13}
14
16 : QObject(control)
17 , _control(control)
18 , _fact(fact)
19 , _vehicle(vehicle)
20{
21 qCDebug(QGCCameraParamIOLog) << this;
22
23 _paramWriteTimer.setSingleShot(true);
24 _paramWriteTimer.setInterval(3000);
25 _paramRequestTimer.setSingleShot(true);
26 _paramRequestTimer.setInterval(3500);
27
28 if (_fact->writeOnly()) {
29 // Write mode is always "done" as it won't ever read
30 _done = true;
31 } else {
32 (void) connect(&_paramRequestTimer, &QTimer::timeout, this, &QGCCameraParamIO::_paramRequestTimeout);
33 }
34 (void) connect(&_paramWriteTimer, &QTimer::timeout, this, &QGCCameraParamIO::_paramWriteTimeout);
35 (void) connect(_fact, &Fact::rawValueChanged, this, &QGCCameraParamIO::_factChanged);
36 (void) connect(_fact, &Fact::containerRawValueChanged, this, &QGCCameraParamIO::_containerRawValueChanged);
37
38 switch (_fact->type()) {
41 _mavParamType = MAV_PARAM_EXT_TYPE_UINT8;
42 break;
44 _mavParamType = MAV_PARAM_EXT_TYPE_INT8;
45 break;
47 _mavParamType = MAV_PARAM_EXT_TYPE_UINT16;
48 break;
50 _mavParamType = MAV_PARAM_EXT_TYPE_INT16;
51 break;
53 _mavParamType = MAV_PARAM_EXT_TYPE_UINT32;
54 break;
56 _mavParamType = MAV_PARAM_EXT_TYPE_UINT64;
57 break;
59 _mavParamType = MAV_PARAM_EXT_TYPE_INT64;
60 break;
62 _mavParamType = MAV_PARAM_EXT_TYPE_REAL32;
63 break;
65 _mavParamType = MAV_PARAM_EXT_TYPE_REAL64;
66 break;
67 // String and custom are the same for now
70 _mavParamType = MAV_PARAM_EXT_TYPE_CUSTOM;
71 break;
72 default:
73 qCWarning(QGCCameraParamIOLog) << "Unsupported fact type" << _fact->type() << "for" << _fact->name();
74 Q_FALLTHROUGH();
76 _mavParamType = MAV_PARAM_EXT_TYPE_INT32;
77 break;
78 }
79}
80
82{
83 qCDebug(QGCCameraParamIOLog) << this;
84}
85
86void QGCCameraParamIO::_paramRequestTimeout()
87{
88 if (++_requestRetries > kMaxRetries) {
89 qCWarning(QGCCameraParamIOLog) << "No response for param request:" << _fact->name();
90 if (!_done) {
91 _done = true;
92 _control->_paramDone();
93 }
94 } else {
95 // Request it again
96 qCDebug(QGCCameraParamIOLog) << "Param request retry:" << _fact->name();
97 paramRequest(false);
98 _paramRequestTimer.start();
99 }
100}
101
102void QGCCameraParamIO::_paramWriteTimeout()
103{
104 if (++_sentRetries > kMaxRetries) {
105 qCWarning(QGCCameraParamIOLog) << "No response for param set:" << _fact->name();
106 _updateOnSet = false;
107 } else {
108 // Send it again
109 qCDebug(QGCCameraParamIOLog) << "Param set retry:" << _fact->name() << _sentRetries;
110 _sendParameter();
111 _paramWriteTimer.start();
112 }
113}
114
115void QGCCameraParamIO::_factChanged(const QVariant &value)
116{
117 Q_UNUSED(value);
118
119 if (!_forceUIUpdate) {
120 qCDebug(QGCCameraParamIOLog) << "UI Fact" << _fact->name() << "changed to" << value;
121 _control->factChanged(_fact);
122 }
123}
124
125void QGCCameraParamIO::_containerRawValueChanged(const QVariant &value)
126{
127 Q_UNUSED(value);
128
129 if (!_fact->readOnly()) {
130 qCDebug(QGCCameraParamIOLog) << "Update Fact from camera" << _fact->name();
131 _sentRetries = 0;
132 _sendParameter();
133 }
134}
135
136void QGCCameraParamIO::_sendParameter()
137{
138 SharedLinkInterfacePtr sharedLink = _vehicle->vehicleLinkManager()->primaryLink().lock();
139 if (sharedLink) {
140 mavlink_param_ext_set_t p{};
141 p.param_type = _mavParamType;
142
143 QGCMAVLink::param_ext_union_t union_value{};
144 const FactMetaData::ValueType_t factType = _fact->type();
145 bool ok = true;
146 switch (factType) {
149 union_value.param_uint8 = static_cast<uint8_t>(_fact->rawValue().toUInt(&ok));
150 break;
152 union_value.param_int8 = static_cast<int8_t>(_fact->rawValue().toInt(&ok));
153 break;
155 union_value.param_uint16 = static_cast<uint16_t>(_fact->rawValue().toUInt(&ok));
156 break;
158 union_value.param_int16 = static_cast<int16_t>(_fact->rawValue().toInt(&ok));
159 break;
161 union_value.param_uint32 = static_cast<uint32_t>(_fact->rawValue().toUInt(&ok));
162 break;
164 union_value.param_int64 = static_cast<int64_t>(_fact->rawValue().toLongLong(&ok));
165 break;
167 union_value.param_uint64 = static_cast<uint64_t>(_fact->rawValue().toULongLong(&ok));
168 break;
170 union_value.param_float = _fact->rawValue().toFloat(&ok);
171 break;
173 union_value.param_double = _fact->rawValue().toDouble(&ok);
174 break;
175 // String and custom are the same for now
178 const QByteArray custom = _fact->rawValue().toByteArray();
179 (void) memcpy(union_value.bytes, custom.constData(), static_cast<size_t>(std::max(custom.size(), static_cast<qsizetype>(MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN))));
180 break;
181 }
182 default:
183 qCCritical(QGCCameraParamIOLog) << "Unsupported fact type" << factType << "for" << _fact->name();
184 Q_FALLTHROUGH();
186 union_value.param_int32 = static_cast<int32_t>(_fact->rawValue().toInt(&ok));
187 break;
188 }
189
190 if (!ok) {
191 qCCritical(QGCCameraParamIOLog) << "Invalid value for" << _fact->name() << ":" << _fact->rawValue();
192 }
193
194 (void) memcpy(&p.param_value[0], &union_value.bytes[0], MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN);
195 p.target_system = static_cast<uint8_t>(_vehicle->id());
196 p.target_component = static_cast<uint8_t>(_control->compID());
197 (void) qstrncpy(p.param_id, _fact->name().toStdString().c_str(), MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_ID_LEN);
198
199 mavlink_message_t msg{};
200 (void) mavlink_msg_param_ext_set_encode_chan(
201 static_cast<uint8_t>(MAVLinkProtocol::instance()->getSystemId()),
202 static_cast<uint8_t>(MAVLinkProtocol::getComponentId()),
203 sharedLink->mavlinkChannel(),
204 &msg,
205 &p
206 );
207 (void) _vehicle->sendMessageOnLinkThreadSafe(sharedLink.get(), msg);
208 }
209
210 _paramWriteTimer.start();
211}
212
213void QGCCameraParamIO::handleParamAck(const mavlink_param_ext_ack_t &ack)
214{
215 _paramWriteTimer.stop();
216
217 switch (ack.param_result) {
218 case PARAM_ACK_ACCEPTED: {
219 QVariant val = _valueFromMessage(ack.param_value, ack.param_type);
220 if (_fact->rawValue() != val) {
221 _fact->containerSetRawValue(val);
222 if(_updateOnSet) {
223 _updateOnSet = false;
224 _control->factChanged(_fact);
225 }
226 }
227 break;
228 }
229 case PARAM_ACK_IN_PROGRESS:
230 // Wait a bit longer for this one
231 qCDebug(QGCCameraParamIOLog) << "Param set in progress:" << _fact->name();
232 _paramWriteTimer.start();
233 break;
234 case PARAM_ACK_FAILED:
235 if (++_sentRetries < kMaxRetries) {
236 // Try again
237 qCWarning(QGCCameraParamIOLog) << "Param set failed:" << _fact->name() << _sentRetries;
238 _paramWriteTimer.start();
239 }
240 break;
241 case PARAM_ACK_VALUE_UNSUPPORTED:
242 qCWarning(QGCCameraParamIOLog) << "Param set unsuported:" << _fact->name();
243 Q_FALLTHROUGH();
244 default: {
245 // If UI changed and value was not set, restore UI
246 QVariant val = _valueFromMessage(ack.param_value, ack.param_type);
247 if (_fact->rawValue() != val) {
248 if (_control->validateParameter(_fact, val)) {
249 _fact->containerSetRawValue(val);
250 }
251 }
252 break;
253 }
254 }
255}
256
257QVariant QGCCameraParamIO::_valueFromMessage(const char *value, uint8_t param_type)
258{
259 QVariant var;
260 QGCMAVLink::param_ext_union_t u{};
261 (void) memcpy(u.bytes, value, MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN);
262 switch (param_type) {
263 case MAV_PARAM_EXT_TYPE_REAL32:
264 var = QVariant(u.param_float);
265 break;
266 case MAV_PARAM_EXT_TYPE_UINT8:
267 var = QVariant(u.param_uint8);
268 break;
269 case MAV_PARAM_EXT_TYPE_INT8:
270 var = QVariant(u.param_int8);
271 break;
272 case MAV_PARAM_EXT_TYPE_UINT16:
273 var = QVariant(u.param_uint16);
274 break;
275 case MAV_PARAM_EXT_TYPE_INT16:
276 var = QVariant(u.param_int16);
277 break;
278 case MAV_PARAM_EXT_TYPE_UINT32:
279 var = QVariant(u.param_uint32);
280 break;
281 case MAV_PARAM_EXT_TYPE_INT32:
282 var = QVariant(u.param_int32);
283 break;
284 case MAV_PARAM_EXT_TYPE_UINT64:
285 var = QVariant(static_cast<quint64>(u.param_uint64));
286 break;
287 case MAV_PARAM_EXT_TYPE_INT64:
288 var = QVariant(static_cast<qint64>(u.param_int64));
289 break;
290 case MAV_PARAM_EXT_TYPE_CUSTOM: {
291 // This will null terminate the name string
292 char strValueWithNull[MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN + 1] = {};
293 (void) strncpy(strValueWithNull, value, MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN);
294 const QString strValue(strValueWithNull);
295 var = QVariant(strValue);
296 break;
297 }
298 default:
299 var = QVariant(0);
300 qCCritical(QGCCameraParamIOLog) << "Invalid param_type used for camera setting:" << param_type;
301 break;
302 }
303
304 return var;
305}
306
307void QGCCameraParamIO::handleParamValue(const mavlink_param_ext_value_t &value)
308{
309 _paramRequestTimer.stop();
310
311 QVariant newValue = _valueFromMessage(value.param_value, value.param_type);
312 if (_control->incomingParameter(_fact, newValue)) {
313 _fact->containerSetRawValue(newValue);
314 _control->factChanged(_fact);
315 }
316 _paramRequestReceived = true;
317
318 if (_forceUIUpdate) {
319 emit _fact->rawValueChanged(_fact->rawValue());
320 emit _fact->valueChanged(_fact->rawValue());
321 _forceUIUpdate = false;
322 }
323
324 if (!_done) {
325 _done = true;
326 _control->_paramDone();
327 }
328
329 qCDebug(QGCCameraParamIOLog) << QStringLiteral("handleParamValue() %1 %2").arg(_fact->name(), _fact->rawValueString());
330}
331
333{
334 // If it's write only, we don't request it.
335 if (_fact->writeOnly()) {
336 if (!_done) {
337 _done = true;
338 _control->_paramDone();
339 }
340 return;
341 }
342
343 if (reset) {
344 _requestRetries = 0;
345 _forceUIUpdate = true;
346 }
347
348 qCDebug(QGCCameraParamIOLog) << "Request parameter:" << _fact->name();
349 SharedLinkInterfacePtr sharedLink = _vehicle->vehicleLinkManager()->primaryLink().lock();
350 if (sharedLink) {
351 char param_id[MAVLINK_MSG_PARAM_EXT_REQUEST_READ_FIELD_PARAM_ID_LEN + 1] = {};
352 (void) strncpy(param_id, _fact->name().toStdString().c_str(), MAVLINK_MSG_PARAM_EXT_REQUEST_READ_FIELD_PARAM_ID_LEN);
353 mavlink_message_t msg{};
354 (void) mavlink_msg_param_ext_request_read_pack_chan(
355 static_cast<uint8_t>(MAVLinkProtocol::instance()->getSystemId()),
356 static_cast<uint8_t>(MAVLinkProtocol::getComponentId()),
357 sharedLink->mavlinkChannel(),
358 &msg,
359 static_cast<uint8_t>(_vehicle->id()),
360 static_cast<uint8_t>(_control->compID()),
361 param_id,
362 -1
363 );
364 _vehicle->sendMessageOnLinkThreadSafe(sharedLink.get(), msg);
365 }
366 _paramRequestTimer.start();
367}
368
370{
371 qCDebug(QGCCameraParamIOLog) << "Send Fact" << _fact->name();
372 _sentRetries = 0;
373 _updateOnSet = updateUI;
374 _sendParameter();
375}
376
378{
379 if (!_fact->writeOnly()) {
380 _paramRequestReceived = false;
381 _requestRetries = 0;
382 _paramRequestTimer.start();
383 }
384}
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
A Fact is used to hold a single value within the system.
Definition Fact.h:19
void rawValueChanged(const QVariant &value)
void containerRawValueChanged(const QVariant &value)
This signal is meant for use by Fact container implementations. Used to send changed values to vehicl...
void valueChanged(const QVariant &value)
This signal is only meant for use by the QT property system. It should not be connected to by client ...
static int getComponentId()
Get the component id of this application.
static MAVLinkProtocol * instance()
int getSystemId() const
Get the system id of this application.
Abstract base class for all camera controls: real and simulated.
virtual void _paramDone()=0
virtual void factChanged(Fact *pFact)=0
Notify controller a parameter has changed.
virtual bool incomingParameter(Fact *pFact, QVariant &newValue)=0
Allow controller to modify or invalidate incoming parameter.
virtual int compID() const =0
virtual bool validateParameter(Fact *pFact, QVariant &newValue)=0
Allow controller to modify or invalidate parameter change.
Camera parameter handler.
Definition QGCCameraIO.h:17
QGCCameraParamIO(MavlinkCameraControl *control, Fact *fact, Vehicle *vehicle)
void handleParamAck(const mavlink_param_ext_ack_t &ack)
void sendParameter(bool updateUI=false)
void handleParamValue(const mavlink_param_ext_value_t &value)
void paramRequest(bool reset=true)
WeakLinkInterfacePtr primaryLink() const
VehicleLinkManager * vehicleLinkManager()
Definition Vehicle.h:580
int id() const
Definition Vehicle.h:425
bool sendMessageOnLinkThreadSafe(LinkInterface *link, mavlink_message_t message)
Definition Vehicle.cc:1470