dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
uavtalk.cpp
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  *
30  * Additional note on redistribution: The copyright and license notices above
31  * must be maintained in each individual source file that is a derivative work
32  * of this source file; otherwise redistribution is prohibited.
33  */
34 
35 #include "uavtalk.h"
36 #include <QtEndian>
37 #include <QDebug>
40 
41 // #define UAVTALK_DEBUG
42 #ifdef UAVTALK_DEBUG
43 #define UAVTALK_QXTLOG_DEBUG(...) qDebug() << __VA_ARGS__
44 #else // UAVTALK_DEBUG
45 #define UAVTALK_QXTLOG_DEBUG(...)
46 #endif // UAVTALK_DEBUG
47 
48 #define SYNC_VAL 0x3C
49 
50 const quint8 UAVTalk::crc_table[256] = {
51  0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
52  0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
53  0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
54  0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
55  0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
56  0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
57  0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
58  0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
59  0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
60  0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
61  0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
62  0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
63  0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
64  0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
65  0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
66  0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3
67 };
68 
72 UAVTalk::UAVTalk(QIODevice *iodev, UAVObjectManager *objMngr, bool canBlock)
73 {
74  io = iodev;
75 
76  this->objMngr = objMngr;
77  this->canBlock = canBlock;
78 
79  startOffset = 0;
80  filledBytes = 0;
81 
82  memset(&stats, 0, sizeof(ComStats));
83 
84  connect(io.data(), &QIODevice::readyRead, this, &UAVTalk::processInputStream);
85 }
86 
88 {
89  // According to Qt, it is not necessary to disconnect upon
90  // object deletion.
91  // disconnect(io, SIGNAL(readyRead()), this, SLOT(processInputStream()));
92 }
93 
98 {
100 
101  memset(&stats, 0, sizeof(ComStats));
102 
103  return ret;
104 }
105 
109 void UAVTalk::processInputStream()
110 {
111  while (io && io->isReadable()) {
112  if (startOffset > (sizeof(rxBuffer) - MAX_PACKET_LENGTH)) {
113  /* If we're not sure there's room for a frame, shift things left in
114  * the buffer so that we can do a bigger read.
115  */
117 
119  startOffset = 0;
120  }
121 
122  int bytes = io->read(reinterpret_cast<char *>(rxBuffer + filledBytes),
123  sizeof(rxBuffer) - filledBytes);
124 
125  if (bytes <= 0) {
126  return;
127  }
128 
129  filledBytes += bytes;
130  stats.rxBytes += bytes;
131 
132  while (processInput());
133  }
134 }
135 
143 bool UAVTalk::sendObjectRequest(UAVObject *obj, bool allInstances)
144 {
145  return objectTransaction(obj, TYPE_OBJ_REQ, allInstances);
146 }
147 
155 bool UAVTalk::sendObject(UAVObject *obj, bool acked, bool allInstances)
156 {
157  if (acked) {
158  return objectTransaction(obj, TYPE_OBJ_ACK, allInstances);
159  } else {
160  return objectTransaction(obj, TYPE_OBJ, allInstances);
161  }
162 }
163 
174 bool UAVTalk::objectTransaction(UAVObject *obj, quint8 type, bool allInstances)
175 {
176  if (type == TYPE_OBJ_ACK || type == TYPE_OBJ_REQ || type == TYPE_OBJ) {
177  return transmitObject(obj, type, allInstances);
178  } else {
179  return false;
180  }
181 }
182 
189 bool UAVTalk::receiveFileChunk(quint32 fileId, quint8 *data, quint32 length)
190 {
191  UAVTalkFileData *hdr = reinterpret_cast<UAVTalkFileData *>(data);
192 
193  if (length < sizeof(*hdr)) {
194  return false;
195  }
196 
197  data += sizeof(*hdr);
198  length -= sizeof(*hdr);
199 
200  // qDebug() << "Received file chunk, file=" << fileId << ", offset = " <<
201  // hdr->offset << ", len=" << length << ", flags=" << hdr->flags;
202 
203  emit fileDataReceived(fileId, hdr->offset, data, length, !!(hdr->flags & FILEDATA_FLAG_EOF),
204  !!(hdr->flags & FILEDATA_FLAG_LAST));
205 
206  return true;
207 }
208 
215 {
216  unsigned int bytesAvail = filledBytes - startOffset;
217 
218  if (bytesAvail < sizeof(UAVTalkHeader)) {
219  return false;
220  }
221 
222  UAVTalkHeader *hdr = reinterpret_cast<UAVTalkHeader *>(rxBuffer + startOffset);
223 
224  /* Basic framing checks. If these fail, skip forward one byte and retry
225  * to capture stream sync.
226  */
227  if (hdr->sync != SYNC_VAL) {
228  startOffset++;
229  stats.rxErrors++;
230 
231  return true;
232  }
233 
234  if ((hdr->type & VER_MASK) != TYPE_VER) {
235  startOffset++;
236  stats.rxErrors++;
237 
238  return true;
239  }
240 
241  if (hdr->size < sizeof(UAVTalkHeader)) {
242  startOffset++;
243  stats.rxErrors++;
244 
245  return true;
246  }
247 
248  /* OK, let's ensure we have enough bytes for the whole frame.
249  * Size doesn't include CRC, so add one.
250  */
251 
252  if ((hdr->size + 1u) > bytesAvail) {
253  return false;
254  }
255 
256  quint8 ourCrc = updateCRC(0, rxBuffer + startOffset, hdr->size);
257  quint8 *theirCrc = rxBuffer + startOffset + hdr->size;
258 
259  if (ourCrc != *theirCrc) {
260  /* Since we can't trust hdr->size for sure, we should just skip
261  * forward one byte.
262  */
263 
264  startOffset++;
265  stats.rxErrors++;
266 
267  return true;
268  }
269 
270  quint8 *payload = rxBuffer + startOffset + sizeof(*hdr);
271  unsigned int payloadBytes = hdr->size - sizeof(*hdr);
272 
273  /* At this point, we'll advance startOffset for the entire length of
274  * frame, and not touch startOffset again this function!
275  */
276  startOffset += hdr->size + 1;
277 
278  /* OK, we have a complete frame as encoded on the wire. Time to do things
279  * with it.
280  */
281  quint8 rxType = hdr->type & TYPE_MASK;
282 
283  quint32 rxObjId = qFromLittleEndian(hdr->objId);
284 
285  if (rxType == TYPE_FILEDATA) {
286  return receiveFileChunk(rxObjId, payload, payloadBytes);
287  }
288 
289  UAVObject *rxObj = objMngr->getObject(rxObjId);
290 
291  if (rxObj == nullptr) {
292  stats.rxErrors++;
293  UAVTALK_QXTLOG_DEBUG("UAVTalk: unknown object");
294 
295  if (rxType == TYPE_OBJ_REQ || rxType == TYPE_OBJ_ACK) {
296  UAVTALK_QXTLOG_DEBUG("UAVTalk: (transmitting NACK)");
297  transmitNack(rxObjId);
298  }
299 
300  return true;
301  }
302 
303  quint16 rxInstId = 0;
304 
305  if (!rxObj->isSingleInstance()) {
306  if ((rxType != TYPE_NACK) || (payloadBytes == 2)) {
307  /* Receiving the instid is optional on an nack-- can just mean
308  * "nack everything" */
309  rxInstId = *(payload++);
310  rxInstId |= *(payload++) << 8;
311 
312  payloadBytes -= 2;
313  }
314  }
315 
316  /* XXX timestamps */
317 
318  // Check data length
319  if (rxType == TYPE_OBJ_REQ || rxType == TYPE_ACK || rxType == TYPE_NACK) {
320  if (payloadBytes != 0) {
321  UAVTALK_QXTLOG_DEBUG("UAVTalk: Unexpected data in req/ack/nack");
322  stats.rxErrors++;
323 
324  return true;
325  }
326  } else {
327  if (payloadBytes != rxObj->getNumBytes()) {
328  UAVTALK_QXTLOG_DEBUG("UAVTalk: Unexpected payload size for obj");
329  stats.rxErrors++;
330 
331  return true;
332  }
333  }
334 
335  receiveObject(rxType, rxObjId, rxInstId, payload, payloadBytes);
336  stats.rxObjectBytes += payloadBytes;
337  stats.rxObjects++;
338 
339  // Done
340  return true;
341 }
342 
353 bool UAVTalk::receiveObject(quint8 type, quint32 objId, quint16 instId, quint8 *data,
354  quint32 length)
355 {
356  Q_UNUSED(length);
357  UAVObject *obj = nullptr;
358  bool error = false;
359  bool allInstances = (instId == ALL_INSTANCES);
360 
361  // Process message type
362  switch (type) {
363  case TYPE_OBJ: // We have received an object.
364  // All instances, not allowed for OBJ messages
365  if (!allInstances) {
366  // Get object and update its data
367  obj = updateObject(objId, instId, data);
368  if (obj == nullptr) {
369  UAVTALK_QXTLOG_DEBUG(
370  QString("[uavtalk.cpp ] Received a UAVObject update for a UAVObject we don't "
371  "know about OBJID:%0 INSTID:%1")
372  .arg(QString(QString("0x") + QString::number(objId, 16).toUpper()))
373  .arg(instId));
374  error = true;
375  }
376  } else {
377  error = true;
378  }
379  break;
380  case TYPE_OBJ_ACK: // We have received an object and are asked for an ACK
381  // All instances, not allowed for OBJ_ACK messages
382  if (!allInstances) {
383  // Get object and update its data
384  obj = updateObject(objId, instId, data);
385  // Transmit ACK
386  if (obj != nullptr) {
387  transmitObject(obj, TYPE_ACK, false);
388  } else {
389  UAVTALK_QXTLOG_DEBUG(QString("[uavtalk.cpp ] Received an acknowledged UAVObject "
390  "update for a UAVObject we don't know about:")
391  .arg(obj->getName()));
392  transmitNack(objId);
393  error = true;
394  }
395  } else {
396  error = true;
397  }
398  break;
399  case TYPE_OBJ_REQ: // We are being asked for an object
400  // Get object, if all instances are requested get instance 0 of the object
401  if (allInstances) {
402  obj = objMngr->getObject(objId);
403  } else {
404  obj = objMngr->getObject(objId, instId);
405  }
406  // If object was found transmit it
407  if (obj != nullptr) {
408  transmitObject(obj, TYPE_OBJ, allInstances);
409  } else {
410  // Object was not found, transmit a NACK with the
411  // objId which was not found.
412  transmitNack(objId);
413  error = true;
414  }
415  break;
416  case TYPE_NACK: // We have received a NACK for an object that does not exist on the remote end.
417  // (but should exist on our end)
418  // All instances, if nacked, are substantially the same as the first
419  // inst being nack'd.
420  if (allInstances) {
421  instId = 0;
422  }
423 
424  // Get object
425  obj = objMngr->getObject(objId, instId);
426  // Check if object exists:
427  if (obj != nullptr) {
428  UAVTALK_QXTLOG_DEBUG(
429  QString("[uavtalk.cpp ] The %0 UAVObject does not exist on the remote end, "
430  "got a Nack")
431  .arg(obj->getName()
432  + QString(QString(" 0x") + QString::number(objId, 16).toUpper())));
433  emit nackReceived(obj);
434  } else {
435  UAVTALK_QXTLOG_DEBUG(
436  QString("[uavtalk.cpp ] Critical error: Received a Nack for an unknown "
437  "UAVObject:%0")
438  .arg(QString(QString("0x") + QString::number(objId, 16).toUpper())));
439  error = true;
440  }
441  break;
442  case TYPE_ACK: // We have received a ACK, supposedly after sending an object with OBJ_ACK
443  // All instances, not allowed for ACK messages
444  if (!allInstances) {
445  // Get object
446  obj = objMngr->getObject(objId, instId);
447  UAVTALK_QXTLOG_DEBUG(
448  QString("[uavtalk.cpp ] Got ack for instance:%0 of UAVObject:%1 with ID:%2")
449  .arg(instId)
450  .arg(obj->getName())
451  .arg(QString(QString("0x") + QString::number(objId, 16).toUpper())));
452  // Check if we actually know this object (tiny chance the ObjID
453  // could be unknown and got through CRC check...)
454  if (obj != nullptr) {
455  UAVTALK_QXTLOG_DEBUG(
456  QString("[uavtalk.cpp ] UAVObject name:%0").arg(obj->getName()));
457  emit ackReceived(obj);
458  } else {
459  error = true;
460  }
461  }
462  break;
463  default:
464  error = true;
465  }
466  // Done (exit value is "success", hence the "!" below)
467  return !error;
468 }
469 
475 UAVObject *UAVTalk::updateObject(quint32 objId, quint16 instId, quint8 *data)
476 {
477  // Get object
478  UAVObject *obj = objMngr->getObject(objId, instId);
479  // If the instance does not exist create it
480  if (obj == nullptr) {
481  // Get the object type
482  UAVObject *tobj = objMngr->getObject(objId);
483  if (tobj == nullptr) {
484  return nullptr;
485  }
486  // Make sure this is a data object
487  UAVDataObject *dobj = dynamic_cast<UAVDataObject *>(tobj);
488  if (dobj == nullptr) {
489  return nullptr;
490  }
491  // Create a new instance, unpack and register
492  UAVDataObject *instobj = dobj->clone(instId);
493  if (!objMngr->registerObject(instobj)) {
494  return nullptr;
495  }
496  instobj->unpack(data);
497  return instobj;
498  } else {
499  // Unpack data into object instance
500  obj->unpack(data);
501  return obj;
502  }
503 }
504 
512 bool UAVTalk::transmitObject(UAVObject *obj, quint8 type, bool allInstances)
513 {
514  // If all instances are requested on a single instance object it is an error
515  if (allInstances && obj->isSingleInstance()) {
516  allInstances = false;
517  }
518 
519  // Process message type
520  if (type == TYPE_OBJ || type == TYPE_OBJ_ACK) {
521  if (allInstances) {
522  // Get number of instances
523  quint32 numInst = objMngr->getNumInstances(obj->getObjID());
524  // Send all instances
525  for (quint32 instId = 0; instId < numInst; ++instId) {
526  UAVObject *inst = objMngr->getObject(obj->getObjID(), instId);
527  transmitSingleObject(inst, type, false);
528  }
529  return true;
530  } else {
531  return transmitSingleObject(obj, type, false);
532  }
533  } else if (type == TYPE_OBJ_REQ) {
534  return transmitSingleObject(obj, TYPE_OBJ_REQ, allInstances);
535  } else if (type == TYPE_ACK) {
536  if (!allInstances) {
537  return transmitSingleObject(obj, TYPE_ACK, false);
538  } else {
539  return false;
540  }
541  } else {
542  return false;
543  }
544 }
545 
552 bool UAVTalk::transmitNack(quint32 objId)
553 {
554  txBuffer[0] = SYNC_VAL;
555  txBuffer[1] = TYPE_VER | TYPE_NACK;
556 
557  qToLittleEndian<quint32>(objId, &txBuffer[4]);
558 
559  return transmitFrame(8, false);
560 }
561 
568 bool UAVTalk::transmitFrame(quint32 length, bool incrTxObj)
569 {
570  if (length >= 256) {
571  Q_ASSERT(0);
572  return false;
573  }
574 
575  txBuffer[2] = length;
576  txBuffer[3] = 0;
577 
578  txBuffer[length] = updateCRC(0, txBuffer, length);
579 
580  // QFileDevice, used for saving logs, has quite a large buffer, we're not worried about it blocking
581  bool blocked = canBlock && io->bytesToWrite() >= TX_BACKLOG_SIZE;
582 
583  if (!io.isNull() && io->isWritable() && !blocked) {
584  io->write(reinterpret_cast<const char *>(txBuffer), length + CHECKSUM_LENGTH);
585  } else {
586  UAVTALK_QXTLOG_DEBUG("UAVTalk: TX refused");
587  ++stats.txErrors;
588  return false;
589  }
590 
591  // Update stats
592  if (incrTxObj) {
593  ++stats.txObjects;
594  /* This can end up counting instance IDs as object length, but big
595  * woop / I think this is arguably correct.
596  */
598  }
599 
600  stats.txBytes += length + CHECKSUM_LENGTH;
601 
602  return true;
603 }
604 
610 bool UAVTalk::requestFile(quint32 fileId, quint32 offset)
611 {
612  txBuffer[0] = SYNC_VAL;
614  qToLittleEndian<quint32>(fileId, &txBuffer[4]);
615  qToLittleEndian<quint32>(offset, &txBuffer[8]);
616  txBuffer[12] = 0;
617  txBuffer[13] = 0;
618 
619  // qDebug() << "Sent file req offs=" << offset;
620 
621  return transmitFrame(14);
622 }
623 
630 bool UAVTalk::transmitSingleObject(UAVObject *obj, quint8 type, bool allInstances)
631 {
632  qint32 length;
633  qint32 dataOffset;
634  quint32 objId;
635  quint16 instId;
636  quint16 allInstId = ALL_INSTANCES;
637 
638  // Setup type and object id fields
639  objId = obj->getObjID();
640  txBuffer[0] = SYNC_VAL;
641  txBuffer[1] = TYPE_VER | type;
642  qToLittleEndian<quint32>(objId, &txBuffer[4]);
643 
644  // Setup instance ID if one is required
645  if (obj->isSingleInstance()) {
646  dataOffset = 8;
647  } else {
648  // Check if all instances are requested
649  if (allInstances) {
650  qToLittleEndian<quint16>(allInstId, &txBuffer[8]);
651  } else {
652  instId = obj->getInstID();
653  qToLittleEndian<quint16>(instId, &txBuffer[8]);
654  }
655  dataOffset = 10;
656  }
657 
658  // Determine data length
659  if (type == TYPE_OBJ_REQ || type == TYPE_ACK) {
660  length = 0;
661  } else {
662  length = obj->getNumBytes();
663  }
664 
665  // Check length
666  if (length >= MAX_PAYLOAD_LENGTH) {
667  return false;
668  }
669 
670  // Copy data (if any)
671  if (length > 0) {
672  if (!obj->pack(&txBuffer[dataOffset])) {
673  return false;
674  }
675  }
676 
677  return transmitFrame(dataOffset + length);
678 }
679 
699 quint8 UAVTalk::updateCRC(quint8 crc, const quint8 *data, qint32 length)
700 {
701  while (length--)
702  crc = crc_table[crc ^ *data++];
703  return crc;
704 }
quint8 rxBuffer[MAX_PACKET_LENGTH *12]
Definition: uavtalk.h:141
qint32 unpack(const quint8 *dataIn)
Definition: uavobject.cpp:270
qint32 pack(quint8 *dataOut)
Definition: uavobject.cpp:255
bool receiveObject(quint8 type, quint32 objId, quint16 instId, quint8 *data, quint32 length)
Definition: uavtalk.cpp:353
bool objectTransaction(UAVObject *obj, quint8 type, bool allInstances)
Definition: uavtalk.cpp:174
static const int TYPE_OBJ_ACK
Definition: uavtalk.h:94
bool registerObject(UAVDataObject *obj)
bool receiveFileChunk(quint32 fileId, quint8 *data, quint32 length)
Definition: uavtalk.cpp:189
static const quint8 crc_table[256]
Definition: uavtalk.h:113
bool canBlock
Definition: uavtalk.h:137
quint32 txObjectBytes
Definition: uavtalk.h:55
quint32 txBytes
Definition: uavtalk.h:53
static const int MAX_PACKET_LENGTH
Definition: uavtalk.h:105
quint32 rxErrors
Definition: uavtalk.h:60
bool sendObject(UAVObject *obj, bool acked, bool allInstances)
Definition: uavtalk.cpp:155
bool transmitNack(quint32 objId)
Definition: uavtalk.cpp:552
ComStats stats
Definition: uavtalk.h:149
static const int TYPE_FILEDATA
Definition: uavtalk.h:98
UAVTalk(QIODevice *iodev, UAVObjectManager *objMngr, bool canBlock=true)
Definition: uavtalk.cpp:72
ComStats getStats()
Definition: uavtalk.cpp:97
static const int TYPE_VER
Definition: uavtalk.h:91
quint32 getInstID()
Definition: uavobject.cpp:115
DataFields data
static const int TYPE_OBJ
Definition: uavtalk.h:92
static const int TYPE_MASK
Definition: uavtalk.h:89
quint32 filledBytes
Definition: uavtalk.h:147
quint32 txObjects
Definition: uavtalk.h:58
static const int TYPE_OBJ_REQ
Definition: uavtalk.h:93
~UAVTalk()
Definition: uavtalk.cpp:87
bool isSingleInstance()
Definition: uavobject.cpp:123
static const int TYPE_ACK
Definition: uavtalk.h:95
quint32 startOffset
Definition: uavtalk.h:146
static const int MAX_PAYLOAD_LENGTH
Definition: uavtalk.h:107
quint32 rxBytes
Definition: uavtalk.h:54
void fileDataReceived(quint32 fileId, quint32 offset, quint8 *data, quint32 dataLen, bool eof, bool lastInSeq)
quint32 rxObjectBytes
Definition: uavtalk.h:56
bool transmitFrame(quint32 length, bool incrTxObj=true)
Definition: uavtalk.cpp:568
static const quint8 FILEDATA_FLAG_LAST
Definition: uavtalk.h:131
UAVObject * updateObject(quint32 objId, quint16 instId, quint8 *data)
Definition: uavtalk.cpp:475
quint32 getObjID()
Definition: uavobject.cpp:107
static const int VER_MASK
Definition: uavtalk.h:88
static const quint8 FILEDATA_FLAG_EOF
Definition: uavtalk.h:130
bool processInput()
Definition: uavtalk.cpp:214
void ackReceived(UAVObject *obj)
QPointer< QIODevice > io
Definition: uavtalk.h:135
static const int TYPE_FILEREQ
Definition: uavtalk.h:97
quint32 getNumBytes()
Definition: uavobject.cpp:155
quint32 rxObjects
Definition: uavtalk.h:57
QString getName()
Definition: uavobject.cpp:131
UAVObjectManager * objMngr
Definition: uavtalk.h:136
static const int CHECKSUM_LENGTH
Definition: uavtalk.h:103
static const int TYPE_NACK
Definition: uavtalk.h:96
static const quint16 ALL_INSTANCES
Definition: uavtalk.h:109
virtual UAVDataObject * clone(quint32 instID=0)=0
bool transmitSingleObject(UAVObject *obj, quint8 type, bool allInstances)
Definition: uavtalk.cpp:630
quint8 txBuffer[MAX_PACKET_LENGTH]
Definition: uavtalk.h:142
else error('Your technical computing program does not support file choosers.Please input the file name in the argument. ') end elseif nargin >0 logfile
static const int TX_BACKLOG_SIZE
Definition: uavtalk.h:112
bool requestFile(quint32 fileId, quint32 offset)
Definition: uavtalk.cpp:610
bool transmitObject(UAVObject *obj, quint8 type, bool allInstances)
Definition: uavtalk.cpp:512
quint8 updateCRC(quint8 crc, const quint8 *data, qint32 length)
Definition: uavtalk.cpp:699
UAVObject * getObject(const QString &name, quint32 instId=0)
static const int MIN_HEADER_LENGTH
Definition: uavtalk.h:100
function crc
quint32 txErrors
Definition: uavtalk.h:59
qint32 getNumInstances(const QString &name)
bool sendObjectRequest(UAVObject *obj, bool allInstances)
Definition: uavtalk.cpp:143
void nackReceived(UAVObject *obj)