2#include "MAVLinkInstanceFields.h"
8#include <QtCore/QTimeZone>
16 , _instanceValue(instanceValue)
18 qCDebug(MAVLinkMessageLog) <<
this;
20 const mavlink_message_info_t *
const msgInfo = mavlink_get_message_info(&message);
22 qCWarning(MAVLinkMessageLog) << QStringLiteral(
"QGCMAVLinkMessage NULL msgInfo msgid(%1)").arg(message.msgid);
26 _name = QString(msgInfo->name);
27 if (!_instanceValue.isEmpty()) {
28 _name += QStringLiteral(
" [%1]").arg(_instanceValue);
30 qCDebug(MAVLinkMessageLog) <<
"New Message:" << _name;
32 for (
unsigned int i = 0; i < msgInfo->num_fields; ++i) {
33 QString type = QStringLiteral(
"?");
34 switch (msgInfo->fields[i].type) {
35 case MAVLINK_TYPE_CHAR: type = QString(
"char");
break;
36 case MAVLINK_TYPE_UINT8_T: type = QString(
"uint8_t");
break;
37 case MAVLINK_TYPE_INT8_T: type = QString(
"int8_t");
break;
38 case MAVLINK_TYPE_UINT16_T: type = QString(
"uint16_t");
break;
39 case MAVLINK_TYPE_INT16_T: type = QString(
"int16_t");
break;
40 case MAVLINK_TYPE_UINT32_T: type = QString(
"uint32_t");
break;
41 case MAVLINK_TYPE_INT32_T: type = QString(
"int32_t");
break;
42 case MAVLINK_TYPE_FLOAT: type = QString(
"float");
break;
43 case MAVLINK_TYPE_DOUBLE: type = QString(
"double");
break;
44 case MAVLINK_TYPE_UINT64_T: type = QString(
"uint64_t");
break;
45 case MAVLINK_TYPE_INT64_T: type = QString(
"int64_t");
break;
47 qCWarning(MAVLinkMessageLog) <<
"Unknown MAVLink field type:" << msgInfo->fields[i].type;
51 const unsigned int array_length = msgInfo->fields[i].array_length;
52 const QString fieldName = QString(msgInfo->fields[i].name);
54 if (array_length > 0 && msgInfo->fields[i].type != MAVLINK_TYPE_CHAR) {
56 for (
unsigned int j = 0; j < array_length; ++j) {
57 const QString elementName = QStringLiteral(
"%1[%2]").arg(fieldName).arg(j);
59 _fields->append(field);
60 _fieldMappings.append({i,
static_cast<int>(j)});
64 _fields->append(field);
65 _fieldMappings.append({i, -1});
74 qCDebug(MAVLinkMessageLog) <<
this;
79 const QString instanceFieldName = mavlinkInstanceFields().value(message.msgid);
80 if (instanceFieldName.isEmpty()) {
82 return _extractDebugInstanceValue(message);
85 const mavlink_message_info_t *
const msgInfo = mavlink_get_message_info(&message);
90 const uint8_t *
const payload =
reinterpret_cast<const uint8_t*
>(&message.payload64[0]);
92 for (
unsigned int i = 0; i < msgInfo->num_fields; ++i) {
93 if (instanceFieldName != QLatin1String(msgInfo->fields[i].name)) {
97 const unsigned int offset = msgInfo->fields[i].wire_offset;
98 const unsigned int array_length = msgInfo->fields[i].array_length;
100 switch (msgInfo->fields[i].type) {
101 case MAVLINK_TYPE_CHAR:
102 if (array_length > 0) {
103 char buf[MAVLINK_MAX_PAYLOAD_LEN + 1]{};
104 memcpy(buf, payload + offset, array_length);
105 buf[array_length] =
'\0';
106 return QString::fromLatin1(buf).trimmed();
108 return QString(QChar::fromLatin1(
static_cast<char>(*(payload + offset))));
110 case MAVLINK_TYPE_UINT8_T:
111 return QString::number(*(payload + offset));
112 case MAVLINK_TYPE_INT8_T:
113 return QString::number(*
reinterpret_cast<const int8_t*
>(payload + offset));
114 case MAVLINK_TYPE_UINT16_T: {
116 memcpy(&val, payload + offset,
sizeof(val));
117 return QString::number(val);
119 case MAVLINK_TYPE_INT16_T: {
121 memcpy(&val, payload + offset,
sizeof(val));
122 return QString::number(val);
124 case MAVLINK_TYPE_UINT32_T: {
126 memcpy(&val, payload + offset,
sizeof(val));
127 return QString::number(val);
129 case MAVLINK_TYPE_INT32_T: {
131 memcpy(&val, payload + offset,
sizeof(val));
132 return QString::number(val);
134 case MAVLINK_TYPE_UINT64_T: {
136 memcpy(&val, payload + offset,
sizeof(val));
137 return QString::number(val);
139 case MAVLINK_TYPE_INT64_T: {
141 memcpy(&val, payload + offset,
sizeof(val));
142 return QString::number(val);
152QString QGCMAVLinkMessage::_extractDebugInstanceValue(
const mavlink_message_t &message)
154 switch (message.msgid) {
155 case MAVLINK_MSG_ID_NAMED_VALUE_FLOAT: {
156 char name[MAVLINK_MSG_NAMED_VALUE_FLOAT_FIELD_NAME_LEN + 1]{};
157 mavlink_msg_named_value_float_get_name(&message,
name);
158 name[MAVLINK_MSG_NAMED_VALUE_FLOAT_FIELD_NAME_LEN] =
'\0';
159 return QString::fromLatin1(
name).trimmed();
161 case MAVLINK_MSG_ID_NAMED_VALUE_INT: {
162 char name[MAVLINK_MSG_NAMED_VALUE_INT_FIELD_NAME_LEN + 1]{};
163 mavlink_msg_named_value_int_get_name(&message,
name);
164 name[MAVLINK_MSG_NAMED_VALUE_INT_FIELD_NAME_LEN] =
'\0';
165 return QString::fromLatin1(
name).trimmed();
167 case MAVLINK_MSG_ID_DEBUG_VECT: {
168 char name[MAVLINK_MSG_DEBUG_VECT_FIELD_NAME_LEN + 1]{};
169 mavlink_msg_debug_vect_get_name(&message,
name);
170 name[MAVLINK_MSG_DEBUG_VECT_FIELD_NAME_LEN] =
'\0';
171 return QString::fromLatin1(
name).trimmed();
173 case MAVLINK_MSG_ID_DEBUG: {
174 return QString::number(mavlink_msg_debug_get_ind(&message));
185 for (
int i = 0; i < _fields->
count(); ++i) {
193 if (sel != _fieldSelected) {
194 _fieldSelected = sel;
201 const quint64 msgCount = _count - _lastCount;
202 const qreal lastRateHz = _actualRateHz;
203 _actualRateHz = (0.2 * _actualRateHz) + (0.8 * msgCount);
205 if (_actualRateHz != lastRateHz) {
212 if (sel != _selected) {
221 if (rate != _targetRateHz) {
222 _targetRateHz = rate;
232 if (_selected || _fieldSelected) {
239void QGCMAVLinkMessage::_updateFields()
241 const mavlink_message_info_t *msgInfo = mavlink_get_message_info(&_message);
243 qCWarning(MAVLinkMessageLog) <<
"QGCMAVLinkMessage::update NULL msgInfo msgid" << _message.msgid;
247 if (_fields->
count() != _fieldMappings.count()) {
248 qCWarning(MAVLinkMessageLog) <<
"QGCMAVLinkMessage::update field mapping count mismatch msgid" << _message.msgid;
252 uint8_t *
const msg =
reinterpret_cast<uint8_t*
>(&_message.payload64[0]);
254 for (
int idx = 0; idx < _fieldMappings.count(); ++idx) {
260 const FieldMapping &mapping = _fieldMappings.at(idx);
261 const unsigned int i = mapping.fieldIndex;
262 const int element = mapping.arrayElement;
263 const unsigned int offset = msgInfo->fields[i].wire_offset;
265 switch (msgInfo->fields[i].type) {
266 case MAVLINK_TYPE_CHAR:
268 if (msgInfo->fields[i].array_length > 0) {
269 char *
const str =
reinterpret_cast<char*
>(msg + offset);
270 str[msgInfo->fields[i].array_length - 1] =
'\0';
271 const QString v(str);
274 char b = *(
reinterpret_cast<char*
>(msg + offset));
279 case MAVLINK_TYPE_UINT8_T:
281 const uint8_t u = *(msg + offset + element);
282 field->
updateValue(QString::number(u),
static_cast<qreal
>(u));
284 const uint8_t u = *(msg + offset);
285 field->
updateValue(QString::number(u),
static_cast<qreal
>(u));
288 case MAVLINK_TYPE_INT8_T:
290 const int8_t n = *(
reinterpret_cast<int8_t*
>(msg + offset) + element);
291 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
293 const int8_t n = *(
reinterpret_cast<int8_t*
>(msg + offset));
294 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
297 case MAVLINK_TYPE_UINT16_T: {
300 (void) memcpy(&n, msg + offset + element *
static_cast<int>(
sizeof(uint16_t)),
303 (void) memcpy(&n, msg + offset,
sizeof(uint16_t));
305 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
308 case MAVLINK_TYPE_INT16_T: {
311 (void) memcpy(&n, msg + offset + element *
static_cast<int>(
sizeof(int16_t)),
314 (void) memcpy(&n, msg + offset,
sizeof(int16_t));
316 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
319 case MAVLINK_TYPE_UINT32_T: {
322 (void) memcpy(&n, msg + offset + element *
static_cast<int>(
sizeof(uint32_t)),
325 (void) memcpy(&n, msg + offset,
sizeof(uint32_t));
327 if (_message.msgid == MAVLINK_MSG_ID_SYSTEM_TIME && element < 0) {
328 const QDateTime d = QDateTime::fromMSecsSinceEpoch(
static_cast<qint64
>(n), QTimeZone::utc());
329 field->
updateValue(d.toString(
"HH:mm:ss"),
static_cast<qreal
>(n));
331 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
335 case MAVLINK_TYPE_INT32_T: {
338 (void) memcpy(&n, msg + offset + element *
static_cast<int>(
sizeof(int32_t)),
341 (void) memcpy(&n, msg + offset,
sizeof(int32_t));
343 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
346 case MAVLINK_TYPE_FLOAT: {
349 (void) memcpy(&fv, msg + offset + element *
static_cast<int>(
sizeof(
float)),
352 (void) memcpy(&fv, msg + offset,
sizeof(
float));
354 field->
updateValue(QString::number(
static_cast<double>(fv),
'g', 10),
static_cast<qreal
>(fv));
357 case MAVLINK_TYPE_DOUBLE: {
360 (void) memcpy(&d, msg + offset + element *
static_cast<int>(
sizeof(
double)),
363 (void) memcpy(&d, msg + offset,
sizeof(
double));
365 field->
updateValue(QString::number(d,
'g', 15),
static_cast<qreal
>(d));
368 case MAVLINK_TYPE_UINT64_T: {
371 (void) memcpy(&n, msg + offset + element *
static_cast<int>(
sizeof(uint64_t)),
374 (void) memcpy(&n, msg + offset,
sizeof(uint64_t));
376 if (_message.msgid == MAVLINK_MSG_ID_SYSTEM_TIME && element < 0) {
377 const QDateTime d = QDateTime::fromMSecsSinceEpoch(n / 1000, QTimeZone::utc());
378 field->
updateValue(d.toString(
"yyyy MM dd HH:mm:ss"),
static_cast<qreal
>(n));
380 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
384 case MAVLINK_TYPE_INT64_T: {
387 (void) memcpy(&n, msg + offset + element *
static_cast<int>(
sizeof(int64_t)),
390 (void) memcpy(&n, msg + offset,
sizeof(int64_t));
392 field->
updateValue(QString::number(n),
static_cast<qreal
>(n));
396 qCWarning(MAVLinkMessageLog) <<
"Unknown MAVLink field type:" << msgInfo->fields[i].type;
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void updateValue(const QString &newValue, qreal v)
void setSelectable(bool sel)
void setTargetRateHz(int32_t rate)
void targetRateHzChanged()
void setSelected(bool sel)
void update(const mavlink_message_t &message)
void actualRateHzChanged()
void fieldSelectedChanged()
static QString extractInstanceValue(const mavlink_message_t &message)
Extract the instance field value from a raw mavlink message, or empty string if none.
void updateFieldSelection()
Q_INVOKABLE QObject * get(int index)
int count() const override final
void clearAndDeleteContents() override final
Clears the list and calls deleteLater on each entry.