mqttclient_module.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. #include <Python.h>
  2. #include "MQTTClient.h"
  3. #include "LinkedList.h"
  4. static PyObject *MqttV3Error;
  5. static PyObject* mqttv3_create(PyObject* self, PyObject *args)
  6. {
  7. MQTTClient c;
  8. char* serverURI;
  9. char* clientId;
  10. int persistence_option = MQTTCLIENT_PERSISTENCE_DEFAULT;
  11. int rc;
  12. if (!PyArg_ParseTuple(args, "ss|i", &serverURI, &clientId,
  13. &persistence_option))
  14. return NULL;
  15. if (persistence_option != MQTTCLIENT_PERSISTENCE_DEFAULT
  16. && persistence_option != MQTTCLIENT_PERSISTENCE_NONE)
  17. {
  18. PyErr_SetString(PyExc_TypeError, "persistence must be DEFAULT or NONE");
  19. return NULL;
  20. }
  21. rc = MQTTClient_create(&c, serverURI, clientId, persistence_option, NULL);
  22. printf("create MQTTClient pointer %p\n", c);
  23. return Py_BuildValue("ik", rc, c);
  24. }
  25. static List* callbacks = NULL;
  26. typedef struct
  27. {
  28. MQTTClient c;
  29. PyObject *context;
  30. PyObject *cl, *ma, *dc;
  31. } CallbackEntry;
  32. int clientCompare(void* a, void* b)
  33. {
  34. CallbackEntry* e = (CallbackEntry*) a;
  35. return e->c == (MQTTClient) b;
  36. }
  37. void connectionLost(void* context, char* cause)
  38. {
  39. /* call the right Python function, using the context */
  40. PyObject *arglist;
  41. PyObject *result;
  42. CallbackEntry* e = context;
  43. PyGILState_STATE gstate;
  44. gstate = PyGILState_Ensure();
  45. arglist = Py_BuildValue("Os", e->context, cause);
  46. result = PyEval_CallObject(e->cl, arglist);
  47. Py_DECREF(arglist);
  48. PyGILState_Release(gstate);
  49. }
  50. int messageArrived(void* context, char* topicName, int topicLen,
  51. MQTTClient_message* message)
  52. {
  53. PyObject *result = NULL;
  54. CallbackEntry* e = context;
  55. int rc = -99;
  56. PyGILState_STATE gstate;
  57. //printf("messageArrived %s %s %d %.*s\n", PyString_AsString(e->context), topicName, topicLen,
  58. // message->payloadlen, (char*)message->payload);
  59. gstate = PyGILState_Ensure();
  60. if (topicLen == 0)
  61. result = PyEval_CallFunction(e->ma, "Os{ss#sisisisi}", e->context,
  62. topicName, "payload", message->payload, message->payloadlen,
  63. "qos", message->qos, "retained", message->retained, "dup",
  64. message->dup, "msgid", message->msgid);
  65. else
  66. result = PyEval_CallFunction(e->ma, "Os#{ss#sisisisi}", e->context,
  67. topicName, topicLen, "payload", message->payload,
  68. message->payloadlen, "qos", message->qos, "retained",
  69. message->retained, "dup", message->dup, "msgid",
  70. message->msgid);
  71. if (result)
  72. {
  73. if (PyInt_Check(result))
  74. rc = (int) PyInt_AsLong(result);
  75. Py_DECREF(result);
  76. }
  77. PyGILState_Release(gstate);
  78. MQTTClient_free(topicName);
  79. MQTTClient_freeMessage(&message);
  80. return rc;
  81. }
  82. void deliveryComplete(void* context, MQTTClient_deliveryToken dt)
  83. {
  84. PyObject *arglist;
  85. PyObject *result;
  86. CallbackEntry* e = context;
  87. PyGILState_STATE gstate;
  88. gstate = PyGILState_Ensure();
  89. arglist = Py_BuildValue("Oi", e->context, dt);
  90. result = PyEval_CallObject(e->dc, arglist);
  91. Py_DECREF(arglist);
  92. PyGILState_Release(gstate);
  93. }
  94. static PyObject* mqttv3_setcallbacks(PyObject* self, PyObject *args)
  95. {
  96. MQTTClient c;
  97. CallbackEntry* e = NULL;
  98. int rc;
  99. e = malloc(sizeof(CallbackEntry));
  100. if (!PyArg_ParseTuple(args, "kOOOO", &c, (PyObject**) &e->context, &e->cl,
  101. &e->ma, &e->dc))
  102. return NULL;
  103. e->c = c;
  104. printf("setCallbacks MQTTClient pointer %p\n", c);
  105. if ((e->cl != Py_None && !PyCallable_Check(e->cl))
  106. || (e->ma != Py_None && !PyCallable_Check(e->ma))
  107. || (e->dc != Py_None && !PyCallable_Check(e->dc)))
  108. {
  109. PyErr_SetString(PyExc_TypeError,
  110. "3rd, 4th and 5th parameters must be callable or None");
  111. return NULL;
  112. }
  113. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_setCallbacks(c, e, connectionLost,
  114. messageArrived, deliveryComplete);
  115. Py_END_ALLOW_THREADS
  116. if (rc == MQTTCLIENT_SUCCESS)
  117. {
  118. ListElement* temp = NULL;
  119. if ((temp = ListFindItem(callbacks, c, clientCompare)) != NULL)
  120. {
  121. ListDetach(callbacks, temp->content);
  122. free(temp->content);
  123. }
  124. ListAppend(callbacks, e, sizeof(e));
  125. Py_XINCREF(e->cl);
  126. Py_XINCREF(e->ma);
  127. Py_XINCREF(e->dc);
  128. Py_XINCREF(e->context);
  129. }
  130. return Py_BuildValue("i", rc);
  131. }
  132. static PyObject* mqttv3_connect(PyObject* self, PyObject *args)
  133. {
  134. MQTTClient c;
  135. PyObject *pyoptions = NULL, *temp;
  136. MQTTClient_connectOptions options = MQTTClient_connectOptions_initializer;
  137. MQTTClient_willOptions woptions = MQTTClient_willOptions_initializer;
  138. int rc;
  139. if (!PyArg_ParseTuple(args, "k|O", &c, &pyoptions))
  140. return NULL;
  141. printf("connect MQTTClient pointer %p\n", c);
  142. if (!pyoptions)
  143. goto skip;
  144. if (!PyDict_Check(pyoptions))
  145. {
  146. PyErr_SetString(PyExc_TypeError, "2nd parameter must be a dictionary");
  147. return NULL;
  148. }
  149. if ((temp = PyDict_GetItemString(pyoptions, "keepAliveInterval")) != NULL)
  150. {
  151. if (PyInt_Check(temp))
  152. options.keepAliveInterval = (int) PyInt_AsLong(temp);
  153. else
  154. {
  155. PyErr_SetString(PyExc_TypeError,
  156. "keepAliveLiveInterval value must be int");
  157. return NULL;
  158. }
  159. }
  160. if ((temp = PyDict_GetItemString(pyoptions, "cleansession")) != NULL)
  161. {
  162. if (PyInt_Check(temp))
  163. options.cleansession = (int) PyInt_AsLong(temp);
  164. else
  165. {
  166. PyErr_SetString(PyExc_TypeError, "cleansession value must be int");
  167. return NULL;
  168. }
  169. }
  170. if ((temp = PyDict_GetItemString(pyoptions, "reliable")) != NULL)
  171. {
  172. if (PyInt_Check(temp))
  173. options.reliable = (int) PyInt_AsLong(temp);
  174. else
  175. {
  176. PyErr_SetString(PyExc_TypeError, "reliable value must be int");
  177. return NULL;
  178. }
  179. }
  180. if ((temp = PyDict_GetItemString(pyoptions, "will")) != NULL)
  181. {
  182. if (PyDict_Check(temp))
  183. {
  184. PyObject *wtemp = NULL;
  185. if ((wtemp = PyDict_GetItemString(temp, "topicName")) == NULL)
  186. {
  187. PyErr_SetString(PyExc_TypeError,
  188. "will topicName value must be set");
  189. return NULL;
  190. }
  191. else
  192. {
  193. if (PyString_Check(wtemp))
  194. woptions.topicName = PyString_AsString(wtemp);
  195. else
  196. {
  197. PyErr_SetString(PyExc_TypeError,
  198. "will topicName value must be string");
  199. return NULL;
  200. }
  201. }
  202. if ((wtemp = PyDict_GetItemString(temp, "message")) == NULL)
  203. {
  204. PyErr_SetString(PyExc_TypeError,
  205. "will message value must be set");
  206. return NULL;
  207. }
  208. else
  209. {
  210. if (PyString_Check(wtemp))
  211. woptions.message = PyString_AsString(wtemp);
  212. else
  213. {
  214. PyErr_SetString(PyExc_TypeError,
  215. "will message value must be string");
  216. return NULL;
  217. }
  218. }
  219. if ((wtemp = PyDict_GetItemString(temp, "retained")) != NULL)
  220. {
  221. if (PyInt_Check(wtemp))
  222. woptions.retained = (int) PyInt_AsLong(wtemp);
  223. else
  224. {
  225. PyErr_SetString(PyExc_TypeError,
  226. "will retained value must be int");
  227. return NULL;
  228. }
  229. }
  230. if ((wtemp = PyDict_GetItemString(temp, "qos")) != NULL)
  231. {
  232. if (PyInt_Check(wtemp))
  233. woptions.qos = (int) PyInt_AsLong(wtemp);
  234. else
  235. {
  236. PyErr_SetString(PyExc_TypeError,
  237. "will qos value must be int");
  238. return NULL;
  239. }
  240. }
  241. options.will = &woptions;
  242. }
  243. else
  244. {
  245. PyErr_SetString(PyExc_TypeError, "will value must be dictionary");
  246. return NULL;
  247. }
  248. }
  249. if ((temp = PyDict_GetItemString(pyoptions, "username")) != NULL)
  250. {
  251. if (PyString_Check(temp))
  252. options.username = PyString_AsString(temp);
  253. else
  254. {
  255. PyErr_SetString(PyExc_TypeError, "username value must be string");
  256. return NULL;
  257. }
  258. }
  259. if ((temp = PyDict_GetItemString(pyoptions, "password")) != NULL)
  260. {
  261. if (PyString_Check(temp))
  262. options.username = PyString_AsString(temp);
  263. else
  264. {
  265. PyErr_SetString(PyExc_TypeError, "password value must be string");
  266. return NULL;
  267. }
  268. }
  269. skip: Py_BEGIN_ALLOW_THREADS rc = MQTTClient_connect(c, &options);
  270. Py_END_ALLOW_THREADS
  271. return Py_BuildValue("i", rc);
  272. }
  273. static PyObject* mqttv3_disconnect(PyObject* self, PyObject *args)
  274. {
  275. MQTTClient c;
  276. int timeout = 0;
  277. int rc;
  278. if (!PyArg_ParseTuple(args, "k|i", &c, &timeout))
  279. return NULL;
  280. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_disconnect(c, timeout);
  281. Py_END_ALLOW_THREADS
  282. return Py_BuildValue("i", rc);
  283. }
  284. static PyObject* mqttv3_isConnected(PyObject* self, PyObject *args)
  285. {
  286. MQTTClient c;
  287. int rc;
  288. if (!PyArg_ParseTuple(args, "k", &c))
  289. return NULL;
  290. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_isConnected(c);
  291. Py_END_ALLOW_THREADS
  292. return Py_BuildValue("i", rc);
  293. }
  294. static PyObject* mqttv3_subscribe(PyObject* self, PyObject *args)
  295. {
  296. MQTTClient c;
  297. char* topic;
  298. int qos = 2;
  299. int rc;
  300. if (!PyArg_ParseTuple(args, "ks|i", &c, &topic, &qos))
  301. return NULL;
  302. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_subscribe(c, topic, qos);
  303. Py_END_ALLOW_THREADS
  304. return Py_BuildValue("i", rc);
  305. }
  306. static PyObject* mqttv3_subscribeMany(PyObject* self, PyObject *args)
  307. {
  308. MQTTClient c;
  309. PyObject* topicList;
  310. PyObject* qosList;
  311. int count;
  312. char** topics;
  313. int* qoss;
  314. int i, rc = 0;
  315. if (!PyArg_ParseTuple(args, "kOO", &c, &topicList, &qosList))
  316. return NULL;
  317. if (!PySequence_Check(topicList) || !PySequence_Check(qosList))
  318. {
  319. PyErr_SetString(PyExc_TypeError,
  320. "3rd and 4th parameters must be sequences");
  321. return NULL;
  322. }
  323. if ((count = PySequence_Length(topicList)) != PySequence_Length(qosList))
  324. {
  325. PyErr_SetString(PyExc_TypeError,
  326. "3rd and 4th parameters must be sequences of the same length");
  327. return NULL;
  328. }
  329. topics = malloc(count * sizeof(char*));
  330. for (i = 0; i < count; ++i)
  331. topics[i] = PyString_AsString(PySequence_GetItem(topicList, i));
  332. qoss = malloc(count * sizeof(int));
  333. for (i = 0; i < count; ++i)
  334. qoss[i] = (int) PyInt_AsLong(PySequence_GetItem(qosList, i));
  335. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_subscribeMany(c, count, topics,
  336. qoss);
  337. Py_END_ALLOW_THREADS
  338. for (i = 0; i < count; ++i)
  339. PySequence_SetItem(qosList, i, PyInt_FromLong((long) qoss[i]));
  340. free(topics);
  341. free(qoss);
  342. if (rc == MQTTCLIENT_SUCCESS)
  343. return Py_BuildValue("iO", rc, qosList);
  344. else
  345. return Py_BuildValue("i", rc);
  346. }
  347. static PyObject* mqttv3_unsubscribe(PyObject* self, PyObject *args)
  348. {
  349. MQTTClient c;
  350. char* topic;
  351. int rc;
  352. if (!PyArg_ParseTuple(args, "ks", &c, &topic))
  353. return NULL;
  354. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_unsubscribe(c, topic);
  355. Py_END_ALLOW_THREADS
  356. return Py_BuildValue("i", rc);
  357. }
  358. static PyObject* mqttv3_unsubscribeMany(PyObject* self, PyObject *args)
  359. {
  360. MQTTClient c;
  361. PyObject* topicList;
  362. int count;
  363. char** topics;
  364. int i, rc = 0;
  365. if (!PyArg_ParseTuple(args, "kOO", &c, &topicList))
  366. return NULL;
  367. if (!PySequence_Check(topicList))
  368. {
  369. PyErr_SetString(PyExc_TypeError, "3rd parameter must be sequences");
  370. return NULL;
  371. }
  372. count = PySequence_Length(topicList);
  373. topics = malloc(count * sizeof(char*));
  374. for (i = 0; i < count; ++i)
  375. topics[i] = PyString_AsString(PySequence_GetItem(topicList, i));
  376. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_unsubscribeMany(c, count, topics);
  377. Py_END_ALLOW_THREADS
  378. free( topics);
  379. return Py_BuildValue("i", rc);
  380. }
  381. static PyObject* mqttv3_publish(PyObject* self, PyObject *args)
  382. {
  383. MQTTClient c;
  384. char* topicName;
  385. int payloadlen;
  386. void* payload;
  387. int qos = 0;
  388. int retained = 0;
  389. MQTTClient_deliveryToken dt;
  390. int rc;
  391. if (!PyArg_ParseTuple(args, "kss#|ii", &c, &topicName, &payload,
  392. &payloadlen, &qos, &retained))
  393. return NULL;
  394. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_publish(c, topicName, payloadlen,
  395. payload, qos, retained, &dt);
  396. Py_END_ALLOW_THREADS
  397. if (rc == MQTTCLIENT_SUCCESS && qos > 0)
  398. return Py_BuildValue("ii", rc, dt);
  399. else
  400. return Py_BuildValue("i", rc);
  401. }
  402. static PyObject* mqttv3_publishMessage(PyObject* self, PyObject *args)
  403. {
  404. MQTTClient c;
  405. char* topicName;
  406. PyObject *message, *temp;
  407. MQTTClient_message msg = MQTTClient_message_initializer;
  408. MQTTClient_deliveryToken dt;
  409. int rc;
  410. if (!PyArg_ParseTuple(args, "ksO", &c, &topicName, &message))
  411. return NULL;
  412. if (!PyDict_Check(message))
  413. {
  414. PyErr_SetString(PyExc_TypeError, "3rd parameter must be a dictionary");
  415. return NULL;
  416. }
  417. if ((temp = PyDict_GetItemString(message, "payload")) == NULL)
  418. {
  419. PyErr_SetString(PyExc_TypeError, "dictionary must have payload key");
  420. return NULL;
  421. }
  422. if (PyString_Check(temp))
  423. PyString_AsStringAndSize(temp, (char**) &msg.payload,
  424. (Py_ssize_t*) &msg.payloadlen);
  425. else
  426. {
  427. PyErr_SetString(PyExc_TypeError, "payload value must be string");
  428. return NULL;
  429. }
  430. if ((temp = PyDict_GetItemString(message, "qos")) == NULL)
  431. msg.qos = (int) PyInt_AsLong(temp);
  432. if ((temp = PyDict_GetItemString(message, "retained")) == NULL)
  433. msg.retained = (int) PyInt_AsLong(temp);
  434. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_publishMessage(c, topicName, &msg,
  435. &dt);
  436. Py_END_ALLOW_THREADS
  437. if (rc == MQTTCLIENT_SUCCESS && msg.qos > 0)
  438. return Py_BuildValue("ii", rc, dt);
  439. else
  440. return Py_BuildValue("i", rc);
  441. }
  442. static PyObject* mqttv3_waitForCompletion(PyObject* self, PyObject *args)
  443. {
  444. MQTTClient c;
  445. unsigned long timeout = 1000L;
  446. MQTTClient_deliveryToken dt;
  447. int rc;
  448. if (!PyArg_ParseTuple(args, "ki|i", &c, &dt, &timeout))
  449. return NULL;
  450. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_waitForCompletion(c, dt, timeout);
  451. Py_END_ALLOW_THREADS
  452. return Py_BuildValue("i", rc);
  453. }
  454. static PyObject* mqttv3_getPendingDeliveryTokens(PyObject* self, PyObject *args)
  455. {
  456. MQTTClient c;
  457. MQTTClient_deliveryToken* tokens;
  458. int rc;
  459. if (!PyArg_ParseTuple(args, "k", &c))
  460. return NULL;
  461. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_getPendingDeliveryTokens(c, &tokens);
  462. Py_END_ALLOW_THREADS
  463. if (rc == MQTTCLIENT_SUCCESS)
  464. {
  465. int i = 0;
  466. PyObject* dts = PyList_New(0);
  467. while (tokens[i] != -1)
  468. PyList_Append(dts, PyInt_FromLong((long) tokens[i]));
  469. return Py_BuildValue("iO", rc, dts);
  470. }
  471. else
  472. return Py_BuildValue("i", rc);
  473. }
  474. static PyObject* mqttv3_yield(PyObject* self, PyObject *args)
  475. {
  476. if (!PyArg_ParseTuple(args, ""))
  477. return NULL;
  478. Py_BEGIN_ALLOW_THREADS
  479. MQTTClient_yield();
  480. Py_END_ALLOW_THREADS
  481. Py_INCREF( Py_None);
  482. return Py_None;
  483. }
  484. static PyObject* mqttv3_receive(PyObject* self, PyObject *args)
  485. {
  486. MQTTClient c;
  487. unsigned long timeout = 1000L;
  488. int rc;
  489. PyObject* temp = NULL;
  490. char* topicName;
  491. int topicLen;
  492. MQTTClient_message* message;
  493. if (!PyArg_ParseTuple(args, "k|k", &c, &timeout))
  494. return NULL;
  495. Py_BEGIN_ALLOW_THREADS rc = MQTTClient_receive(c, &topicName, &topicLen,
  496. &message, timeout);
  497. Py_END_ALLOW_THREADS
  498. if (message)
  499. {
  500. temp = Py_BuildValue("is#{ss#sisisisi}", rc, topicName, topicLen,
  501. "payload", message->payload, message->payloadlen, "qos",
  502. message->qos, "retained", message->retained, "dup",
  503. message->dup, "msgid", message->msgid);
  504. free(topicName);
  505. MQTTClient_freeMessage(&message);
  506. }
  507. else
  508. temp = Py_BuildValue("iz", rc, NULL);
  509. return temp;
  510. }
  511. static PyObject* mqttv3_destroy(PyObject* self, PyObject *args)
  512. {
  513. MQTTClient c;
  514. ListElement* temp = NULL;
  515. if (!PyArg_ParseTuple(args, "k", &c))
  516. return NULL;
  517. if ((temp = ListFindItem(callbacks, c, clientCompare)) != NULL)
  518. {
  519. ListDetach(callbacks, temp->content);
  520. free(temp->content);
  521. }
  522. MQTTClient_destroy(&c);
  523. Py_INCREF(Py_None);
  524. return Py_None;
  525. }
  526. static PyMethodDef MqttV3Methods[] =
  527. {
  528. { "create", mqttv3_create, METH_VARARGS, "Create an MQTTv3 client." },
  529. { "setcallbacks", mqttv3_setcallbacks, METH_VARARGS,
  530. "Sets the callback functions for a particular client." },
  531. { "connect", mqttv3_connect, METH_VARARGS,
  532. "Connects to a server using the specified options." },
  533. { "disconnect", mqttv3_disconnect, METH_VARARGS,
  534. "Disconnects from a server." },
  535. { "isConnected", mqttv3_isConnected, METH_VARARGS,
  536. "Determines if this client is currently connected to the server." },
  537. { "subscribe", mqttv3_subscribe, METH_VARARGS,
  538. "Subscribe to the given topic." },
  539. { "subscribeMany", mqttv3_subscribeMany, METH_VARARGS,
  540. "Subscribe to the given topics." },
  541. { "unsubscribe", mqttv3_unsubscribe, METH_VARARGS,
  542. "Unsubscribe from the given topic." },
  543. { "unsubscribeMany", mqttv3_unsubscribeMany, METH_VARARGS,
  544. "Unsubscribe from the given topics." },
  545. { "publish", mqttv3_publish, METH_VARARGS,
  546. "Publish a message to the given topic." },
  547. { "publishMessage", mqttv3_publishMessage, METH_VARARGS,
  548. "Publish a message to the given topic." },
  549. { "waitForCompletion", mqttv3_waitForCompletion, METH_VARARGS,
  550. "Waits for the completion of the delivery of the message represented by a delivery token." },
  551. { "getPendingDeliveryTokens", mqttv3_getPendingDeliveryTokens,
  552. METH_VARARGS,
  553. "Returns the delivery tokens pending of completion." },
  554. { "yield", mqttv3_yield, METH_VARARGS,
  555. "Single-thread keep alive but don't receive message." },
  556. { "receive", mqttv3_receive, METH_VARARGS,
  557. "Single-thread receive message if available." },
  558. { "destroy", mqttv3_destroy, METH_VARARGS,
  559. "Free memory allocated to a MQTT client. It is the opposite to create." },
  560. { NULL, NULL, 0, NULL } /* Sentinel */
  561. };
  562. PyMODINIT_FUNC initpaho_mqtt3c(void)
  563. {
  564. PyObject *m;
  565. PyEval_InitThreads();
  566. callbacks = ListInitialize();
  567. m = Py_InitModule("paho_mqtt3c", MqttV3Methods);
  568. if (m == NULL)
  569. return;
  570. MqttV3Error = PyErr_NewException("paho_mqtt3c.error", NULL, NULL);
  571. Py_INCREF(MqttV3Error);
  572. PyModule_AddObject(m, "error", MqttV3Error);
  573. PyModule_AddIntConstant(m, "SUCCESS", MQTTCLIENT_SUCCESS);
  574. PyModule_AddIntConstant(m, "FAILURE", MQTTCLIENT_FAILURE);
  575. PyModule_AddIntConstant(m, "DISCONNECTED", MQTTCLIENT_DISCONNECTED);
  576. PyModule_AddIntConstant(m, "MAX_MESSAGES_INFLIGHT", MQTTCLIENT_MAX_MESSAGES_INFLIGHT);
  577. PyModule_AddIntConstant(m, "BAD_UTF8_STRING", MQTTCLIENT_BAD_UTF8_STRING);
  578. PyModule_AddIntConstant(m, "BAD_NULL_PARAMETER", MQTTCLIENT_NULL_PARAMETER);
  579. PyModule_AddIntConstant(m, "BAD_TOPICNAME_TRUNCATED", MQTTCLIENT_TOPICNAME_TRUNCATED);
  580. PyModule_AddIntConstant(m, "PERSISTENCE_DEFAULT", MQTTCLIENT_PERSISTENCE_DEFAULT);
  581. PyModule_AddIntConstant(m, "PERSISTENCE_NONE", MQTTCLIENT_PERSISTENCE_NONE);
  582. PyModule_AddIntConstant(m, "PERSISTENCE_USER", MQTTCLIENT_PERSISTENCE_USER);
  583. PyModule_AddIntConstant(m, "PERSISTENCE_ERROR",
  584. MQTTCLIENT_PERSISTENCE_ERROR);
  585. }