A project I’ve been working on, and testing in conjunction with tripzero, is something I call CuteIPC. Play on words for an Inter-Process Communication framework based off Nokia’s Qt (pronounced cute). The entire concept for this came from one of many arguments I have with tripzero, in which I proclaim that my monolithic style carpc frontend for the Windows Operating System is more beneficial from both a development and user standpoint than his multi-process Linux based concept. I’ll spout about exactly what that means in a later post.
As I often do, I gave trip the benefit of the doubt. We started discussing the limiting factors of a multi-process approach to a piece of software, and what hurdles would have to be overcome to make multi-process programming efficient. The big one was a lack of a decent cross-platform IPC framework. Qt has internally several IPC classes, however they all had limiting factors that guided us to the decision that we would have to write our own. The idea was to emulate the server-client architecture of dbus, where clients could offer services for any other client to take advantage of.
The implementation details involved the server running a TCP daemon on a offbeat port of localhost, so any client could connect, register its presents on the “bus”, and communicate with other clients connected to the bus. This is about how the typical IPC that I came across had worked. So why write our own? In three words: QObject JSON Proxies. What this does, is it allows me to procedurally generate class definitions of any client on the bus in JSON. Basically defining the interface that is exposed on the bus. Function calls, Signals and Slots, Properties, etc. Once these are defined in JSON, they are transmitted across the bus to any client who requests it. The client can then generate a header in ANY language, using this JSON as a definition file for how to generate the interface header.
Through some fancy code-trickery, this allows an application developer who is writing a GUI application, to access and use say, OBD2 functionality as if it was built into their program, even though it is seamlessly being ported over the IPC. An example is in order I believe.
{ “busname”:”revfeobd”, “name”:”RevFEObd”, “signals”: [ { "name":"pidReply", "args": [ {"type":"QString","name":"mode"}, {"type":"QString","name":"pid"}, {"type":"int","name":"set"}, {"type":"double","name":"time"} ] }, { “name”:”protocolReply”, “args”: [ {"type":"QString","name":"protocol"} ] }, { “name”:”mfgStringReply”, “args”: [ {"type":"QString","name":"mfg"} ] } ] , “slots”: [ { "name":"deleteLater", "args": [ ] }, { “name”:”addPid”, “args”: [ {"type":"QString","name":"pid"} ] } ] }
Looks like a mess dosen’t it? What this actually does, is define an interface for the RevFEObd class on the bus under the name revfeobd. Using this JSON as a template, we can generate this header file:
#include <QObject>
#include <cuteipc.h>
class RevFEObd : public QObject
{
Q_OBJECT
public:
RevFEObd(CuteIpc *ipc) {
m_ipc = ipc;
m_ipc->addObject(this);
ipc->connectFunctionToSlot(“revfeobd”,”RevFEObd”,”pidReply”,this,”pidReplySlot”);
ipc->connectFunctionToSlot(“revfeobd”,”RevFEObd”,”protocolReply”,this,”protocolReplySlot”);
ipc->connectFunctionToSlot(“revfeobd”,”RevFEObd”,”mfgStringReply”,this,”mfgStringReplySlot”);
}
CuteIpc *m_ipc;
signals:
void pidReply( QString mode,QString pid,int set,double time);
void protocolReply( QString protocol);
void mfgStringReply( QString mfg);
public slots:
void pidReplySlot(QString mode,QString pid,int set,double time) {
emit pidReply(mode,pid,set,time);
}
void protocolReplySlot(QString protocol) {
emit protocolReply(protocol);
}
void mfgStringReplySlot(QString mfg) {
emit mfgStringReply(mfg);
}
void deleteLater() {
m_ipc->callFunction(“revfeobd”,”RevFEObd”,”deleteLater”,QList<QVariant>());
}
void addPid(QString pid) {
m_ipc->callFunction(“revfeobd”,”RevFEObd”,”addPid”,QList<QVariant>()<<pid);
}
};
Ignoring all the bad formatting, this is generated procedurally at runtime. You can then compile this header into your application, and you have direct access to OBD2 functionality. Of course this still leaves the option of directly accessing the IPC and sending JSON calls directly, but the header generation provides for a much easier interface for those unfamiliar with JSON. It also allows for generation in languages other than c++. I’ve already gotten mostly written a c# header generator, which will allow for .net applications to take full advantage of anything running on the IPC bus.