mavnative.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. /*
  2. Native mavlink glue for python.
  3. Author: kevinh@geeksville.com
  4. */
  5. #undef NDEBUG
  6. #include <Python.h>
  7. #include <structmember.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <stdint.h>
  11. #include <assert.h>
  12. #include <stddef.h>
  13. #include <setjmp.h>
  14. #if PY_MAJOR_VERSION >= 3
  15. // In python3 it only has longs, not 32 bit ints
  16. #define PyInt_AsLong PyLong_AsLong
  17. #define PyInt_FromLong PyLong_FromLong
  18. // We returns strings for byte arreays in python2, but bytes objects in python3
  19. #define PyByteString_FromString PyBytes_FromString
  20. #define PyByteString_FromStringAndSize PyBytes_FromStringAndSize
  21. #define PyByteString_ConcatAndDel PyBytes_ConcatAndDel
  22. #else
  23. #define PyByteString_FromString PyString_FromString
  24. #define PyByteString_FromStringAndSize PyString_FromStringAndSize
  25. #define PyByteString_ConcatAndDel PyString_ConcatAndDel
  26. #endif
  27. #include "mavlink_defaults.h"
  28. #define MAVLINK_USE_CONVENIENCE_FUNCTIONS
  29. #include <mavlink_types.h>
  30. // Mavlink send support
  31. // Not currently used, but keeps mavlink_helpers send code happy
  32. static mavlink_system_t mavlink_system = {42,11,};
  33. static void comm_send_ch(mavlink_channel_t chan, uint8_t c) {
  34. // Sending not supported yet in native code
  35. assert(0);
  36. }
  37. #define MAVLINK_ASSERT(x) assert(x)
  38. // static mavlink_message_t last_msg;
  39. /*
  40. default message crc function. You can override this per-system to
  41. put this data in a different memory segment
  42. */
  43. #define MAVLINK_MESSAGE_CRC(msgid) py_message_info[msgid].crc_extra
  44. /* Enable this option to check the length of each message.
  45. This allows invalid messages to be caught much sooner. Use if the transmission
  46. medium is prone to missing (or extra) characters (e.g. a radio that fades in
  47. and out). Only use if the channel will only contain messages types listed in
  48. the headers.
  49. */
  50. #define MAVLINK_MESSAGE_LENGTH(msgid) py_message_info[msgid].len
  51. // #include <mavlink.h>
  52. #define TRUE 1
  53. #define FALSE 0
  54. typedef struct {
  55. PyObject *name; // name of this field
  56. mavlink_message_type_t type; // type of this field
  57. unsigned int array_length; // if non-zero, field is an array
  58. unsigned int wire_offset; // offset of each field in the payload
  59. } py_field_info_t;
  60. // note that in this structure the order of fields is the order
  61. // in the XML file, not necessary the wire order
  62. typedef struct {
  63. PyObject *id; // The int id for this msg
  64. PyObject *name; // name of the message
  65. unsigned len; // the raw message length of this message - not including headers & CRC
  66. uint8_t crc_extra; // the CRC extra for this message
  67. unsigned num_fields; // how many fields in this message
  68. PyObject *fieldnames; // fieldnames in the correct order expected by user (not wire order)
  69. py_field_info_t fields[MAVLINK_MAX_FIELDS]; // field information
  70. } py_message_info_t;
  71. static py_message_info_t py_message_info[256];
  72. static uint8_t info_inited = FALSE; // We only do the init once (assuming only one dialect in use)
  73. #include <protocol.h>
  74. /**
  75. * Contains a structure mavlink_message but also the raw bytes that make up that message
  76. */
  77. typedef struct {
  78. mavlink_message_t msg;
  79. int numBytes;
  80. uint8_t bytes[MAVLINK_MAX_PACKET_LEN];
  81. } py_message_t;
  82. typedef struct {
  83. PyObject_HEAD
  84. PyObject *MAVLinkMessage;
  85. mavlink_status_t mav_status;
  86. py_message_t msg;
  87. } NativeConnection;
  88. // #define MAVNATIVE_DEBUG
  89. #ifdef MAVNATIVE_DEBUG
  90. # define mavdebug printf
  91. #else
  92. # define mavdebug(x...)
  93. #endif
  94. // My exception type
  95. static PyObject *MAVNativeError;
  96. static jmp_buf python_entry;
  97. #define PYTHON_ENTRY if(!setjmp(python_entry)) {
  98. #define PYTHON_EXIT } else { return NULL; } // Used for routines thar return ptrs
  99. #define PYTHON_EXIT_INT } else { return -1; } // Used for routines that return ints
  100. /** (originally from mavlink_helpers.h - but now customized to not be channel based)
  101. * This is a convenience function which handles the complete MAVLink parsing.
  102. * the function will parse one byte at a time and return the complete packet once
  103. * it could be successfully decoded. Checksum and other failures will be silently
  104. * ignored.
  105. *
  106. * Messages are parsed into an internal buffer (one for each channel). When a complete
  107. * message is received it is copies into *returnMsg and the channel's status is
  108. * copied into *returnStats.
  109. *
  110. * @param c The char to parse
  111. *
  112. * @param returnMsg NULL if no message could be decoded, the message data else
  113. * @param returnStats if a message was decoded, this is filled with the channel's stats
  114. * @return 0 if no message could be decoded, 1 else
  115. *
  116. */
  117. MAVLINK_HELPER uint8_t py_mavlink_parse_char(uint8_t c, py_message_t* pymsg, mavlink_status_t* status)
  118. {
  119. mavlink_message_t *rxmsg = &pymsg->msg;
  120. int bufferIndex = 0;
  121. status->msg_received = 0;
  122. switch (status->parse_state)
  123. {
  124. case MAVLINK_PARSE_STATE_UNINIT:
  125. case MAVLINK_PARSE_STATE_IDLE:
  126. if (c == MAVLINK_STX)
  127. {
  128. status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
  129. rxmsg->len = 0;
  130. pymsg->numBytes = 0;
  131. rxmsg->magic = c;
  132. mavlink_start_checksum(rxmsg);
  133. pymsg->bytes[pymsg->numBytes++] = c;
  134. }
  135. break;
  136. case MAVLINK_PARSE_STATE_GOT_STX:
  137. if (status->msg_received
  138. /* Support shorter buffers than the
  139. default maximum packet size */
  140. #if (MAVLINK_MAX_PAYLOAD_LEN < 255)
  141. || c > MAVLINK_MAX_PAYLOAD_LEN
  142. #endif
  143. )
  144. {
  145. status->buffer_overrun++;
  146. status->parse_error++;
  147. status->msg_received = 0;
  148. status->parse_state = MAVLINK_PARSE_STATE_IDLE;
  149. }
  150. else
  151. {
  152. // NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2
  153. rxmsg->len = c;
  154. status->packet_idx = 0;
  155. mavlink_update_checksum(rxmsg, c);
  156. pymsg->bytes[pymsg->numBytes++] = c;
  157. status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH;
  158. }
  159. break;
  160. case MAVLINK_PARSE_STATE_GOT_LENGTH:
  161. rxmsg->seq = c;
  162. mavlink_update_checksum(rxmsg, c);
  163. pymsg->bytes[pymsg->numBytes++] = c;
  164. status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ;
  165. break;
  166. case MAVLINK_PARSE_STATE_GOT_SEQ:
  167. rxmsg->sysid = c;
  168. mavlink_update_checksum(rxmsg, c);
  169. pymsg->bytes[pymsg->numBytes++] = c;
  170. status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID;
  171. break;
  172. case MAVLINK_PARSE_STATE_GOT_SYSID:
  173. rxmsg->compid = c;
  174. mavlink_update_checksum(rxmsg, c);
  175. pymsg->bytes[pymsg->numBytes++] = c;
  176. status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID;
  177. break;
  178. case MAVLINK_PARSE_STATE_GOT_COMPID:
  179. #ifdef MAVLINK_CHECK_MESSAGE_LENGTH
  180. if (rxmsg->len != MAVLINK_MESSAGE_LENGTH(c))
  181. {
  182. status->parse_error++;
  183. status->parse_state = MAVLINK_PARSE_STATE_IDLE;
  184. break;
  185. }
  186. #endif
  187. rxmsg->msgid = c;
  188. mavlink_update_checksum(rxmsg, c);
  189. pymsg->bytes[pymsg->numBytes++] = c;
  190. if (rxmsg->len == 0)
  191. {
  192. status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD;
  193. }
  194. else
  195. {
  196. status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID;
  197. }
  198. break;
  199. case MAVLINK_PARSE_STATE_GOT_MSGID:
  200. _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx++] = (char)c;
  201. mavlink_update_checksum(rxmsg, c);
  202. pymsg->bytes[pymsg->numBytes++] = c;
  203. if (status->packet_idx == rxmsg->len)
  204. {
  205. status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD;
  206. }
  207. break;
  208. case MAVLINK_PARSE_STATE_GOT_PAYLOAD:
  209. #if MAVLINK_CRC_EXTRA
  210. mavlink_update_checksum(rxmsg, MAVLINK_MESSAGE_CRC(rxmsg->msgid));
  211. #endif
  212. pymsg->bytes[pymsg->numBytes++] = c;
  213. if (c != (rxmsg->checksum & 0xFF)) {
  214. // Check first checksum byte
  215. status->parse_error++;
  216. status->msg_received = 0;
  217. status->parse_state = MAVLINK_PARSE_STATE_IDLE;
  218. if (c == MAVLINK_STX)
  219. {
  220. status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
  221. rxmsg->len = 0;
  222. mavlink_start_checksum(rxmsg);
  223. }
  224. }
  225. else
  226. {
  227. status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1;
  228. _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx] = (char)c;
  229. }
  230. break;
  231. case MAVLINK_PARSE_STATE_GOT_CRC1:
  232. pymsg->bytes[pymsg->numBytes++] = c;
  233. if (c != (rxmsg->checksum >> 8)) {
  234. // Check second checksum byte
  235. status->parse_error++;
  236. status->msg_received = 0;
  237. status->parse_state = MAVLINK_PARSE_STATE_IDLE;
  238. if (c == MAVLINK_STX)
  239. {
  240. status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
  241. rxmsg->len = 0;
  242. mavlink_start_checksum(rxmsg);
  243. }
  244. }
  245. else
  246. {
  247. // Successfully got message
  248. status->msg_received = 1;
  249. status->parse_state = MAVLINK_PARSE_STATE_IDLE;
  250. _MAV_PAYLOAD_NON_CONST(rxmsg)[status->packet_idx+1] = (char)c;
  251. }
  252. break;
  253. case MAVLINK_PARSE_STATE_GOT_BAD_CRC1: // not used, just to fix compiler warning
  254. break;
  255. }
  256. bufferIndex++;
  257. // If a message has been sucessfully decoded, check index
  258. if (status->msg_received == 1)
  259. {
  260. //while(status->current_seq != rxmsg->seq)
  261. //{
  262. // status->packet_rx_drop_count++;
  263. // status->current_seq++;
  264. //}
  265. status->current_rx_seq = rxmsg->seq;
  266. // Initial condition: If no packet has been received so far, drop count is undefined
  267. if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0;
  268. // Count this packet as received
  269. status->packet_rx_success_count++;
  270. }
  271. return status->msg_received;
  272. }
  273. // Raise a python exception
  274. static void set_pyerror(const char *msg) {
  275. PyErr_SetString(MAVNativeError, msg);
  276. }
  277. // Pass assertion failures back to python (if we can)
  278. extern void __assert_fail(const char *__assertion, const char *__file, unsigned int __line, const char *__function)
  279. {
  280. char msg[256];
  281. sprintf(msg, "Assertion failed: %s, %s:%d", __assertion, __file, __line);
  282. set_pyerror(msg);
  283. longjmp(python_entry, 1);
  284. }
  285. static unsigned get_field_size(int field_type) {
  286. unsigned fieldSize;
  287. switch(field_type)
  288. {
  289. case MAVLINK_TYPE_CHAR:
  290. fieldSize = 1;
  291. break;
  292. case MAVLINK_TYPE_UINT8_T:
  293. fieldSize = 1;
  294. break;
  295. case MAVLINK_TYPE_INT8_T:
  296. fieldSize = 1;
  297. break;
  298. case MAVLINK_TYPE_UINT16_T:
  299. fieldSize = 2;
  300. break;
  301. case MAVLINK_TYPE_INT16_T:
  302. fieldSize = 2;
  303. break;
  304. case MAVLINK_TYPE_UINT32_T:
  305. fieldSize = 4;
  306. break;
  307. case MAVLINK_TYPE_INT32_T:
  308. fieldSize = 4;
  309. break;
  310. case MAVLINK_TYPE_UINT64_T:
  311. fieldSize = 8;
  312. break;
  313. case MAVLINK_TYPE_INT64_T:
  314. fieldSize = 8;
  315. break;
  316. case MAVLINK_TYPE_FLOAT:
  317. fieldSize = 4;
  318. break;
  319. case MAVLINK_TYPE_DOUBLE:
  320. fieldSize = 8;
  321. break;
  322. default:
  323. mavdebug("BAD MAV TYPE %d\n", field_type);
  324. set_pyerror("Unexpected mavlink type");
  325. fieldSize = 1;
  326. }
  327. return fieldSize;
  328. }
  329. /**
  330. * Given a python type character & array_size advance the wire_offset to the correct next value.
  331. * @return the equivalent C++ type code.
  332. */
  333. static int get_py_typeinfo(char type_char, int array_size, unsigned *wire_offset)
  334. {
  335. int type_code;
  336. switch(type_char)
  337. {
  338. case 'f': type_code = MAVLINK_TYPE_FLOAT; break;
  339. case 'd': type_code = MAVLINK_TYPE_DOUBLE; break;
  340. case 'c': type_code = MAVLINK_TYPE_CHAR; break;
  341. case 'v': type_code = MAVLINK_TYPE_UINT8_T; break;
  342. case 'b': type_code = MAVLINK_TYPE_INT8_T; break;
  343. case 'B': type_code = MAVLINK_TYPE_UINT8_T; break;
  344. case 'h': type_code = MAVLINK_TYPE_INT16_T; break;
  345. case 'H': type_code = MAVLINK_TYPE_UINT16_T; break;
  346. case 'i': type_code = MAVLINK_TYPE_INT32_T; break;
  347. case 'I': type_code = MAVLINK_TYPE_UINT32_T; break;
  348. case 'q': type_code = MAVLINK_TYPE_INT64_T; break;
  349. case 'Q': type_code = MAVLINK_TYPE_UINT64_T; break;
  350. default:
  351. assert(0);
  352. }
  353. int total_len = get_field_size(type_code) * (array_size == 0 ? 1 : array_size);
  354. *wire_offset += total_len;
  355. return type_code;
  356. }
  357. /**
  358. We preconvert message info from the C style representation to python objects (to minimize # of object allocs).
  359. FIXME - we really should free these PyObjects if our module gets unloaded.
  360. @param mavlink_map - the mavlink_map object from python a dict from an int msgid -> tuple(fmt, type_class, order_list, len_list, crc_extra)
  361. */
  362. static void init_message_info(PyObject *mavlink_map) {
  363. // static const mavlink_message_info_t src[256] = MAVLINK_MESSAGE_INFO;
  364. PyObject *items_list = PyDict_Values(mavlink_map);
  365. assert(items_list); // A list of the tuples in mavlink_map
  366. Py_ssize_t numMsgs = PyList_Size(items_list);
  367. int i;
  368. for(i = 0; i < numMsgs; i++) {
  369. PyObject *type_class = PyList_GetItem(items_list, i); // returns a _borrowed_ reference
  370. assert(type_class);
  371. PyObject *id_obj = PyObject_GetAttrString(type_class, "id"); // A _new_ reference
  372. assert(id_obj);
  373. PyObject *name_obj = PyObject_GetAttrString(type_class, "name"); // A new reference
  374. assert(name_obj);
  375. PyObject *crc_extra_obj = PyObject_GetAttrString(type_class, "crc_extra"); // A new reference
  376. assert(crc_extra_obj);
  377. PyObject *fieldname_list = PyObject_GetAttrString(type_class, "ordered_fieldnames"); // A new reference
  378. assert(fieldname_list);
  379. //PyObject *order_list = PyObject_GetAttrString(type_class, "orders"); // A new reference
  380. //assert(order_list);
  381. PyObject *arrlen_list = PyObject_GetAttrString(type_class, "array_lengths"); // A new reference
  382. assert(arrlen_list);
  383. PyObject *type_format = PyObject_GetAttrString(type_class, "native_format"); // A new reference
  384. assert(type_format);
  385. char *type_str = PyByteArray_AsString(type_format);
  386. assert(type_str);
  387. Py_ssize_t num_fields = PyList_Size(fieldname_list);
  388. uint8_t id = (uint8_t) PyInt_AsLong(id_obj);
  389. py_message_info_t *d = &py_message_info[id];
  390. d->id = id_obj;
  391. d->name = name_obj;
  392. d->num_fields = num_fields;
  393. d->crc_extra = PyInt_AsLong(crc_extra_obj);
  394. d->fieldnames = PyObject_GetAttrString(type_class, "fieldnames"); // A new reference
  395. assert(d->fieldnames);
  396. int fnum;
  397. unsigned wire_offset = 0;
  398. for(fnum = 0; fnum < num_fields; fnum++) {
  399. PyObject *field_name_obj = PyList_GetItem(fieldname_list, fnum); // returns a _borrowed_ reference
  400. assert(field_name_obj);
  401. Py_INCREF(field_name_obj);
  402. PyObject *len_obj = PyList_GetItem(arrlen_list, fnum); // returns a _borrowed_ reference
  403. assert(len_obj);
  404. d->fields[fnum].name = field_name_obj;
  405. d->fields[fnum].array_length = PyInt_AsLong(len_obj);
  406. char type_char = type_str[1 + fnum];
  407. d->fields[fnum].wire_offset = wire_offset; // Store the current offset before advancing
  408. d->fields[fnum].type = get_py_typeinfo(type_char, d->fields[fnum].array_length, &wire_offset);
  409. }
  410. d->len = wire_offset;
  411. Py_DECREF(crc_extra_obj);
  412. Py_DECREF(arrlen_list);
  413. Py_DECREF(type_format);
  414. //Py_DECREF(order_list);
  415. }
  416. Py_DECREF(items_list);
  417. }
  418. static PyObject *createPyNone(void)
  419. {
  420. Py_INCREF(Py_None);
  421. return Py_None;
  422. }
  423. /**
  424. Set an attribute, but handing over ownership on the value
  425. */
  426. static void set_attribute(PyObject *obj, const char *attrName, PyObject *val) {
  427. assert(val);
  428. PyObject_SetAttrString(obj, attrName, val);
  429. Py_DECREF(val);
  430. }
  431. /**
  432. Extract a field value from a mavlink msg
  433. @return possibly null if mavlink stream is corrupted (FIXME, caller should check)
  434. */
  435. static PyObject *pyextract_mavlink(const mavlink_message_t *msg, const py_field_info_t *field) {
  436. unsigned offset = field->wire_offset;
  437. int index;
  438. // For arrays of chars we build the result in a string instead of an array
  439. PyObject *arrayResult = (field->array_length != 0 && field->type != MAVLINK_TYPE_CHAR) ? PyList_New(field->array_length) : NULL;
  440. PyObject *stringResult = (field->array_length != 0 && field->type == MAVLINK_TYPE_CHAR) ? PyByteString_FromString("") : NULL;
  441. PyObject *result = NULL;
  442. int numValues = (field->array_length == 0) ? 1 : field->array_length;
  443. unsigned fieldSize = get_field_size(field->type);
  444. uint8_t string_ended = FALSE;
  445. if(arrayResult != NULL)
  446. result = arrayResult;
  447. // Either build a full array of results, or return a single value
  448. for(index = 0; index < numValues; index++) {
  449. PyObject *val = NULL;
  450. switch(field->type) {
  451. case MAVLINK_TYPE_CHAR: {
  452. // If we are building a string, stop writing when we see a null char
  453. char c = _MAV_RETURN_char(msg, offset);
  454. if(stringResult && c == 0)
  455. string_ended = TRUE;
  456. val = PyByteString_FromStringAndSize(&c, 1);
  457. break;
  458. }
  459. case MAVLINK_TYPE_UINT8_T:
  460. val = PyInt_FromLong(_MAV_RETURN_uint8_t(msg, offset));
  461. break;
  462. case MAVLINK_TYPE_INT8_T:
  463. val = PyInt_FromLong(_MAV_RETURN_int8_t(msg, offset));
  464. break;
  465. case MAVLINK_TYPE_UINT16_T:
  466. val = PyInt_FromLong(_MAV_RETURN_uint16_t(msg, offset));
  467. break;
  468. case MAVLINK_TYPE_INT16_T:
  469. val = PyInt_FromLong(_MAV_RETURN_int16_t(msg, offset));
  470. break;
  471. case MAVLINK_TYPE_UINT32_T:
  472. val = PyLong_FromLong(_MAV_RETURN_uint32_t(msg, offset));
  473. break;
  474. case MAVLINK_TYPE_INT32_T:
  475. val = PyInt_FromLong(_MAV_RETURN_int32_t(msg, offset));
  476. break;
  477. case MAVLINK_TYPE_UINT64_T:
  478. val = PyLong_FromLongLong(_MAV_RETURN_uint64_t(msg, offset));
  479. break;
  480. case MAVLINK_TYPE_INT64_T:
  481. val = PyLong_FromLongLong(_MAV_RETURN_int64_t(msg, offset));
  482. break;
  483. case MAVLINK_TYPE_FLOAT:
  484. val = PyFloat_FromDouble(_MAV_RETURN_float(msg, offset));
  485. break;
  486. case MAVLINK_TYPE_DOUBLE:
  487. val = PyFloat_FromDouble(_MAV_RETURN_double(msg, offset));
  488. break;
  489. default:
  490. mavdebug("BAD MAV TYPE %d\n", field->type);
  491. set_pyerror("Unexpected mavlink type");
  492. return NULL;
  493. }
  494. offset += fieldSize;
  495. assert(val);
  496. if(arrayResult != NULL)
  497. PyList_SetItem(arrayResult, index, val);
  498. else if(stringResult != NULL) {
  499. if(!string_ended)
  500. PyByteString_ConcatAndDel(&stringResult, val);
  501. else
  502. Py_DECREF(val); // We didn't use this char
  503. result = stringResult;
  504. }
  505. else // Not building an array
  506. result = val;
  507. }
  508. assert(result);
  509. return result;
  510. }
  511. /**
  512. Convert a message to a valid python representation.
  513. @return new message, or null if a valid encoding could not be made
  514. FIXME - move msgclass, the mavstatus and channel context into an instance, created once with the mavfile object
  515. */
  516. static PyObject *msg_to_py(PyObject* msgclass, const py_message_t *pymsg) {
  517. const mavlink_message_t *msg = &pymsg->msg;
  518. const py_message_info_t *info = &py_message_info[msg->msgid];
  519. mavdebug("Found a msg: %s\n", PyString_AS_STRING(info->name));
  520. /* Call the class object to create our instance */
  521. // PyObject *obj = PyObject_CallObject((PyObject *) &NativeConnectionType, null);
  522. PyObject *argList = PyTuple_Pack(2, info->id, info->name);
  523. PyObject *obj = PyObject_CallObject(msgclass, argList);
  524. uint8_t objValid = TRUE;
  525. assert(obj);
  526. Py_DECREF(argList);
  527. // Find the header subobject
  528. PyObject *header = PyObject_GetAttrString(obj, "_header");
  529. assert(header);
  530. // msgid already set in the constructor call
  531. set_attribute(header, "mlen", PyInt_FromLong(msg->len));
  532. set_attribute(header, "seq", PyInt_FromLong(msg->seq));
  533. set_attribute(header, "srcSystem", PyInt_FromLong(msg->sysid));
  534. set_attribute(header, "srcComponent", PyInt_FromLong(msg->compid));
  535. Py_DECREF(header);
  536. header = NULL;
  537. // FIXME - we should generate this expensive field only as needed (via a getattr override)
  538. set_attribute(obj, "_msgbuf", PyByteArray_FromStringAndSize((const char *) pymsg->bytes, pymsg->numBytes));
  539. // Now add all the fields - FIXME - do this lazily using getattr overrides
  540. PyObject_SetAttrString(obj, "_fieldnames", info->fieldnames); // Will increment the reference count
  541. // FIXME - reuse the fieldnames list from python - so it is in the right order
  542. int fnum;
  543. for(fnum = 0; fnum < info->num_fields && objValid; fnum++) {
  544. const py_field_info_t *f = &info->fields[fnum];
  545. PyObject *val = pyextract_mavlink(msg, f);
  546. if(val != NULL) {
  547. PyObject_SetAttr(obj, f->name, val);
  548. Py_DECREF(val); // We no longer need val, the attribute will keep a ref
  549. }
  550. else
  551. objValid = FALSE;
  552. }
  553. if(objValid)
  554. return obj;
  555. else {
  556. Py_DECREF(obj);
  557. return NULL;
  558. }
  559. }
  560. /**
  561. * How many bytes would we like to read to complete current packet
  562. */
  563. static int get_expectedlength(NativeConnection *self)
  564. {
  565. int desired;
  566. mavlink_message_t *msg = &self->msg.msg;
  567. switch(self->mav_status.parse_state) {
  568. case MAVLINK_PARSE_STATE_UNINIT:
  569. case MAVLINK_PARSE_STATE_IDLE:
  570. desired = 8;
  571. break;
  572. case MAVLINK_PARSE_STATE_GOT_STX:
  573. desired = 7;
  574. break;
  575. case MAVLINK_PARSE_STATE_GOT_LENGTH:
  576. desired = msg->len + 6;
  577. break;
  578. case MAVLINK_PARSE_STATE_GOT_SEQ:
  579. desired = msg->len + 5;
  580. break;
  581. case MAVLINK_PARSE_STATE_GOT_SYSID:
  582. desired = msg->len + 4;
  583. break;
  584. case MAVLINK_PARSE_STATE_GOT_COMPID:
  585. desired = msg->len + 3;
  586. break;
  587. case MAVLINK_PARSE_STATE_GOT_MSGID:
  588. desired = msg->len - self->mav_status.packet_idx + 2;
  589. break;
  590. case MAVLINK_PARSE_STATE_GOT_PAYLOAD:
  591. desired = 2;
  592. break;
  593. case MAVLINK_PARSE_STATE_GOT_CRC1:
  594. desired = 1;
  595. break;
  596. default:
  597. // Huh? Just claim 1
  598. desired = 1;
  599. break;
  600. }
  601. mavdebug("in state %d, expected_length=%d\n", (int) self->mav_status.parse_state, desired);
  602. return desired;
  603. }
  604. static PyObject *NativeConnection_getexpectedlength(NativeConnection *self, void *closure)
  605. {
  606. return PyInt_FromLong(get_expectedlength(self));
  607. }
  608. /**
  609. Given a byte array of bytes
  610. @return a list of MAVProxy_message objects
  611. */
  612. static PyObject *
  613. py_parse_chars(NativeConnection *self, PyObject *args)
  614. {
  615. PYTHON_ENTRY
  616. PyObject* byteObj;
  617. if (!PyArg_ParseTuple(args, "O", &byteObj)) {
  618. set_pyerror("Invalid arguments");
  619. return NULL;
  620. }
  621. assert(PyByteArray_Check(byteObj));
  622. Py_ssize_t numBytes = PyByteArray_Size(byteObj);
  623. mavdebug("numbytes %u\n", (unsigned) numBytes);
  624. char *start = PyByteArray_AsString(byteObj);
  625. assert(start);
  626. char *bytes = start;
  627. PyObject *result = NULL;
  628. // Generate a list of messages found
  629. while(numBytes) {
  630. char c = *bytes++;
  631. numBytes--;
  632. get_expectedlength(self); mavdebug("parse 0x%x\n", (unsigned char) c);
  633. if (py_mavlink_parse_char(c, &self->msg, &self->mav_status)) {
  634. mavdebug("got packet\n");
  635. result = msg_to_py(self->MAVLinkMessage, &self->msg);
  636. if(result != NULL)
  637. break;
  638. }
  639. }
  640. // We didn't process all bytes provided by the caller, so fixup their array
  641. memmove(start, bytes, numBytes);
  642. PyByteArray_Resize(byteObj, numBytes);
  643. if(result != NULL)
  644. return result;
  645. else
  646. return createPyNone();
  647. PYTHON_EXIT
  648. }
  649. /**
  650. Given an string of bytes.
  651. This routine is more efficient than parse_chars, because it doesn't need to buffer characters.
  652. @return a list of MAVProxy_message objects
  653. */
  654. static PyObject *
  655. py_parse_buffer(NativeConnection *self, PyObject *args)
  656. {
  657. PYTHON_ENTRY
  658. mavdebug("Enter py_parse_buffer\n");
  659. const char *bytes;
  660. Py_ssize_t numBytes = 0;
  661. if (!PyArg_ParseTuple(args, "s#", &bytes, &numBytes)) {
  662. set_pyerror("Invalid arguments");
  663. return NULL;
  664. }
  665. // mavdebug("numbytes %u\n", (unsigned) numBytes);
  666. PyObject* list = PyList_New(0);
  667. // Generate a list of messages found
  668. while(numBytes--) {
  669. char c = *bytes++;
  670. // mavdebug("parse %c\n", c);
  671. if (py_mavlink_parse_char(c, &self->msg, &self->mav_status)) {
  672. PyObject *obj = msg_to_py(self->MAVLinkMessage, &self->msg);
  673. if(obj != NULL) {
  674. PyList_Append(list, obj);
  675. // Append will have bummped up the ref count on obj, so we need to release our count
  676. Py_DECREF(obj);
  677. }
  678. }
  679. }
  680. return list;
  681. PYTHON_EXIT
  682. }
  683. static PyObject *
  684. NativeConnection_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  685. {
  686. NativeConnection *self = (NativeConnection *)type->tp_alloc(type, 0);
  687. mavdebug("new connection\n");
  688. return (PyObject *)self;
  689. }
  690. static int
  691. NativeConnection_init(NativeConnection *self, PyObject *args, PyObject *kwds)
  692. {
  693. PYTHON_ENTRY
  694. mavdebug("Enter init\n");
  695. memset(&self->mav_status, 0, sizeof(self->mav_status));
  696. PyObject* msgclass, *mavlink_map;
  697. if (!PyArg_ParseTuple(args, "OO", &msgclass, &mavlink_map)) {
  698. set_pyerror("Invalid arguments");
  699. return -1;
  700. }
  701. // keep a ref to our mavlink instance constructor
  702. assert(msgclass);
  703. self->MAVLinkMessage = msgclass;
  704. Py_INCREF(msgclass);
  705. assert(mavlink_map);
  706. if(!info_inited) {
  707. init_message_info(mavlink_map);
  708. info_inited = TRUE;
  709. }
  710. mavdebug("inited connection\n");
  711. return 0;
  712. PYTHON_EXIT_INT
  713. }
  714. static void NativeConnection_dealloc(NativeConnection* self)
  715. {
  716. Py_XDECREF(self->MAVLinkMessage);
  717. Py_TYPE(self)->tp_free((PyObject*)self);
  718. }
  719. static PyMemberDef NativeConnection_members[] = {
  720. {NULL} /* Sentinel */
  721. };
  722. static PyGetSetDef NativeConnection_getseters[] = {
  723. {"expected_length",
  724. (getter)NativeConnection_getexpectedlength, NULL,
  725. "How many characters would the state-machine like to read now",
  726. NULL},
  727. {NULL} /* Sentinel */
  728. };
  729. static PyMethodDef NativeConnection_methods[] = {
  730. {"parse_chars", (PyCFunction) py_parse_chars, METH_VARARGS,
  731. "Given a msg class and an array of bytes, Parse chars, returning a message or None"},
  732. {"parse_buffer", (PyCFunction) py_parse_buffer, METH_VARARGS,
  733. "Given a msg class and a string like object, Parse chars, returning a (possibly empty) list of messages"},
  734. {NULL, NULL},
  735. };
  736. // FIXME - delete this?
  737. static PyTypeObject NativeConnectionType = {
  738. #if PY_MAJOR_VERSION >= 3
  739. PyVarObject_HEAD_INIT(NULL, 0)
  740. #else
  741. PyObject_HEAD_INIT(NULL)
  742. 0, /* ob_size */
  743. #endif
  744. "mavnative.NativeConnection", /* tp_name */
  745. sizeof(NativeConnection), /* tp_basicsize */
  746. 0, /* tp_itemsize */
  747. (destructor)NativeConnection_dealloc, /* tp_dealloc */
  748. 0, /* tp_print */
  749. 0, /* tp_getattr */
  750. 0, /* tp_setattr */
  751. 0, /* tp_compare */
  752. 0, /* tp_repr */
  753. 0, /* tp_as_number */
  754. 0, /* tp_as_sequence */
  755. 0, /* tp_as_mapping */
  756. 0, /* tp_hash */
  757. 0, /* tp_call */
  758. 0, /* tp_str */
  759. 0, /* tp_getattro */
  760. 0, /* tp_setattro */
  761. 0, /* tp_as_buffer */
  762. Py_TPFLAGS_DEFAULT |
  763. Py_TPFLAGS_BASETYPE, /* tp_flags */
  764. "NativeConnection objects", /* tp_doc */
  765. 0, /* tp_traverse */
  766. 0, /* tp_clear */
  767. 0, /* tp_richcompare */
  768. 0, /* tp_weaklistoffset */
  769. 0, /* tp_iter */
  770. 0, /* tp_iternext */
  771. NativeConnection_methods, /* tp_methods */
  772. NativeConnection_members, /* tp_members */
  773. NativeConnection_getseters, /* tp_getset */
  774. 0, /* tp_base */
  775. 0, /* tp_dict */
  776. 0, /* tp_descr_get */
  777. 0, /* tp_descr_set */
  778. 0, /* tp_dictoffset */
  779. (initproc)NativeConnection_init, /* tp_init */
  780. 0, /* tp_alloc */
  781. NativeConnection_new, /* tp_new */
  782. };
  783. #if PY_MAJOR_VERSION >= 3
  784. #define MOD_RETURN(m) return m
  785. #else
  786. #define MOD_RETURN(m) return
  787. #endif
  788. PyMODINIT_FUNC
  789. #if PY_MAJOR_VERSION >= 3
  790. PyInit_mavnative(void)
  791. #else
  792. initmavnative(void)
  793. #endif
  794. {
  795. if (PyType_Ready(&NativeConnectionType) < 0)
  796. MOD_RETURN(NULL);
  797. #if PY_MAJOR_VERSION < 3
  798. static PyMethodDef ModuleMethods[] = {
  799. {NULL, NULL, 0, NULL} /* Sentinel */
  800. };
  801. PyObject *m = Py_InitModule3("mavnative", ModuleMethods, "Mavnative module");
  802. if (m == NULL)
  803. MOD_RETURN(m);
  804. #else
  805. static PyModuleDef mod_def = {
  806. PyModuleDef_HEAD_INIT,
  807. "mavnative",
  808. "EMavnative module",
  809. -1,
  810. NULL, NULL, NULL, NULL, NULL
  811. };
  812. PyObject *m = PyModule_Create(&mod_def);
  813. #endif
  814. MAVNativeError = PyErr_NewException("mavnative.error", NULL, NULL);
  815. Py_INCREF(MAVNativeError);
  816. PyModule_AddObject(m, "error", MAVNativeError);
  817. Py_INCREF(&NativeConnectionType);
  818. PyModule_AddObject(m, "NativeConnection", (PyObject *) &NativeConnectionType);
  819. MOD_RETURN(m);
  820. }