2 * Python binding for the packet.c module.
4 * This file is Copyright (c) 2010 by the GPSD project
5 * BSD terms apply: see the file COPYING in the distribution root for details.
13 static PyObject *ErrorObject = NULL;
15 static PyObject *report_callback = NULL;
17 void gpsd_report(int errlevel, const char *fmt, ... )
23 gpsd_hexdump_level = errlevel;
25 if (!report_callback) /* no callback defined, exit early */
28 if (!PyCallable_Check(report_callback)) {
29 PyErr_SetString(ErrorObject, "Cannot call Python callback function");
34 (void)vsnprintf(buf, sizeof(buf), fmt, ap);
37 args = Py_BuildValue("(is)", errlevel, buf);
41 PyObject_Call(report_callback, args, NULL);
45 static PyTypeObject Lexer_Type;
49 struct gps_packet_t lexer;
53 newLexerObject(PyObject *arg)
56 self = PyObject_New(LexerObject, &Lexer_Type);
59 memset(&self->lexer, 0, sizeof(struct gps_packet_t));
60 packet_reset(&self->lexer);
67 Lexer_init(LexerObject *self)
69 packet_reset(&self->lexer);
74 Lexer_get(LexerObject *self, PyObject *args)
79 if (!PyArg_ParseTuple(args, "i;missing or invalid file descriptor argument to gps.packet.get", &fd))
82 len = packet_get(fd, &self->lexer);
86 return Py_BuildValue("(i, i, s#)",
89 self->lexer.outbuffer,
90 self->lexer.outbuflen);
94 Lexer_reset(LexerObject *self)
96 packet_reset(&self->lexer);
103 Lexer_dealloc(LexerObject *self)
108 static PyMethodDef Lexer_methods[] = {
109 {"get", (PyCFunction)Lexer_get, METH_VARARGS,
110 PyDoc_STR("Get a packet from a file descriptor.")},
111 {"reset", (PyCFunction)Lexer_reset, METH_NOARGS,
112 PyDoc_STR("Reset the packet lexer to ground state.")},
113 {NULL, NULL} /* sentinel */
117 Lexer_getattr(LexerObject *self, char *name)
119 return Py_FindMethod(Lexer_methods, (PyObject *)self, name);
122 PyDoc_STRVAR(Lexer__doc__,
123 "GPS packet lexer object\n\
125 Fetch a single packet from file descriptor");
127 static PyTypeObject Lexer_Type = {
128 /* The ob_type field must be initialized in the module init function
129 * to be portable to Windows without using C++. */
130 PyObject_HEAD_INIT(NULL)
132 "gps.packet.lexer", /*tp_name*/
133 sizeof(LexerObject), /*tp_basicsize*/
136 (destructor)Lexer_dealloc, /*tp_dealloc*/
138 (getattrfunc)Lexer_getattr, /*tp_getattr*/
143 0, /*tp_as_sequence*/
151 Py_TPFLAGS_DEFAULT, /*tp_flags*/
152 Lexer__doc__, /*tp_doc*/
155 0, /*tp_richcompare*/
156 0, /*tp_weaklistoffset*/
159 Lexer_methods, /*tp_methods*/
167 (initproc)Lexer_init, /*tp_init*/
174 /* Function of no arguments returning new Lexer object */
177 gpspacket_new(PyObject *self, PyObject *args)
181 if (!PyArg_ParseTuple(args, ":new"))
183 rv = newLexerObject(args);
186 return (PyObject *)rv;
189 PyDoc_STRVAR(register_report__doc__,
190 "register_report(callback)\n\
192 callback must be a callable object expecting a string as parameter.");
195 register_report(LexerObject *self, PyObject *args)
197 PyObject *callback = NULL;
199 if (!PyArg_ParseTuple(args, "O:register_report", &callback))
202 if (!PyCallable_Check(callback)) {
203 PyErr_SetString(PyExc_TypeError, "First argument must be callable");
207 if (report_callback) {
208 Py_DECREF(report_callback);
209 report_callback = NULL;
212 report_callback = callback;
213 Py_INCREF(report_callback);
220 /* List of functions defined in the module */
222 static PyMethodDef packet_methods[] = {
223 {"new", gpspacket_new, METH_VARARGS,
224 PyDoc_STR("new() -> new packet-lexer object")},
225 {"register_report", (PyCFunction)register_report, METH_VARARGS,
226 register_report__doc__},
227 {NULL, NULL} /* sentinel */
230 PyDoc_STRVAR(module_doc,
231 "Python binding of the libgpsd module for recognizing GPS packets.\n\
232 The new() function returns a new packet-lexer instance. Lexer instances\n\
234 get() takes a file descriptor argument and returns a tuple consisting of\n\
235 the integer packet type and string packet value. On end of file it returns\n\
237 reset() resets the packet-lexer to its initial state.\n\
238 The module also has a register_report() function that accepts a callback\n\
239 for debug message reporting. The callback will get two arguments, the error\n\
240 level of the message and the message itself.\n\
248 if (PyType_Ready(&Lexer_Type) < 0)
251 /* Create the module and add the functions */
252 m = Py_InitModule3("packet", packet_methods, module_doc);
254 PyModule_AddIntConstant(m, "BAD_PACKET", BAD_PACKET);
255 PyModule_AddIntConstant(m, "COMMENT_PACKET", COMMENT_PACKET);
256 PyModule_AddIntConstant(m, "NMEA_PACKET", NMEA_PACKET);
257 PyModule_AddIntConstant(m, "SIRF_PACKET", SIRF_PACKET);
258 PyModule_AddIntConstant(m, "ZODIAC_PACKET", ZODIAC_PACKET);
259 PyModule_AddIntConstant(m, "TSIP_PACKET", TSIP_PACKET);
260 PyModule_AddIntConstant(m, "EVERMORE_PACKET", EVERMORE_PACKET);
261 PyModule_AddIntConstant(m, "ITALK_PACKET", ITALK_PACKET);
262 PyModule_AddIntConstant(m, "GARMIN_PACKET", GARMIN_PACKET);
263 PyModule_AddIntConstant(m, "NAVCOM_PACKET", NAVCOM_PACKET);
264 PyModule_AddIntConstant(m, "RTCM2_PACKET", RTCM2_PACKET);
265 PyModule_AddIntConstant(m, "RTCM3_PACKET", RTCM3_PACKET);
266 PyModule_AddIntConstant(m, "UBX_PACKET", UBX_PACKET);
267 PyModule_AddIntConstant(m, "GARMINTXT_PACKET", GARMINTXT_PACKET);
269 PyModule_AddIntConstant(m, "LOG_IO", LOG_IO);