Category Archives: C++

Returning array of C++ wrapped objects to NodeJS and JavaScript using nan

Lately I had a hard time trying to figure out how to properly wrap simple C++ objects (like structs or so) with limited understanding of object-oriented JS. So I took some time (actually not so long, but sill) and found out that there are no classes in JS so constructing objects is quite tricky as it always use prototype function.

Don’t really like the idea, but well…

Anyway, it was not really straightforward at the beginning to wrap C++ object. A bit easier after figuring out all that function for objects creation. It ends up with creating new wrapping object that has a creating function (I have called it “constructor” using the same naming as in the documentation. My objects are read only (in fact it is a representation of serial devices) and all properties are also read only, so I had to create only getters, called accessors:

So the whole “constructor” template function looks like this:

Then for each getter you can create a method (I liked this way) or create one getter and use the name to distinguish return values. For me it looked like this:

So the last thing is to create the JS object from the C++ object and fill the array. First object creation:

When we do have this we just need to create an JavaScript array with nan and v8:

That’s all, final result looks like this in console:

As always you can see the whole code as a commit on the github:

https://github.com/killpl/obd_cougar/commit/84974d028f5b2669e41db8b4c0ecd54b3d4ebb1b

After finally resolving this problems it is time to go on with UART communication and sending some commands to ELM327 😉

Abstracting serial device from an OS layer

Today a bit about serial communication as it will be a base communication layer ELM327 and CAN communication, just like IP is a base layer for TCP/UDP.

Why abstraction though? Application is currently for OS X so this is not really a must have. On the other hand this is how it usually should be done, especially if we consider multiplatform in the future. This is also not a really big change big difference too and makes code a bit cleaner.

So what do we need? Shortly: a common interface and common types for all parameters and return values. I divided it into two parts, may be the same library finally, but can be also easily split in two. Just the matter of preference. It is:

  • Serial devices enumeration and recognition.
  • Serial device access: open, read, write, close with parameters as baud rate, parity control etc.

First thing is a really OS specific thing, but interestingly quite easy to create an interface. I made a decision to support both Bluetooth and USB serial adapters and tested it with:

Enumeration will be explained in next post, now just an interface:

Easy to use, one method that returns a list of SerialDevice objects that describes serial port and parent objects that describes a specific device that handles serial communication: USB. Bluetooth or Other, unknown device type.

For USB and Bluetooth devices I try to get more specific information about name, vendor etc.

Current implementation is here:

https://github.com/killpl/obd_cougar/blob/master/cougar_lib/serial/IInterfaces.h

Later on I’ve opened the man page for open(): x-man-page://2/open  and made some assumptions for possible errors and parameters:

Man page for open() in Terminal

Next thing, which is currently in progress, is device access and read write. The interface will be much more complicated, as it has to support a lot of open() flags, configuration parameters and errors,

First thing to notice is that we have specific errors in enum, but SerialOpenFlag is a bitmask, so it had to be implemented with consecutive powers of 2: 0x0001, 0x0002, 0x0004, 0x0008… so in a result we might set any bit of the flag without affecting other ones – READ_WRITE and NOBLOCK is for example b’00001100′.

On the other hand the interface cannot be platform specific, so we have to map this later to system specific codes, I decided for it to look like this:

Similar way for error handling for open() operation:

Easy to maintain, easily readable and extendable. Moreover, totally abstract from the OS specific functions 😉

Next post will be about macOS serial devices enumeration and recognition, stay tuned 😉

NodeJS addon with C++ and Objective-C

I have finished the module a few days ago (and it does not work, check the previous post) so now it is a good time to show a bit of technical difficulties and solutions.

First things first – an introduction. What we want is a class (I think in JS more proper name is a  prototype) with a few methods:

  • StartScan – with callback for results.
  • StopScan
  • IsScanning
  • GetState – current state of bluetooth (on/off etc).

We start with a module file – obd_cougar_lib.cc, structure of binding.gyp was described before for that project so I won’t paste it again, this is the file:

https://github.com/killpl/obd_cougar/blob/master/cougar_bluetooth_lib/binding.gyp

I used nan as the whole internet recommended and ended with something like this:

Let’s divide it into parts and describe one by one. First we need a module to export information and module initialization information. First says what we want to export and second is a static function that creates that object:

We use two defines to achieve this – NODE_MODULE  with two parameters: module name and second is initialization function conveniently declared by macro NAN_MODULE_INIT  with one parameter – a name. We export here a class and a function – we don’t have to export just a one thing.

Then we need a class to export – let’s call it Cougar_Bluetooth and init from inside of Init – this is visible in the snippet above. Next create a class:

There  static NAN_MODULE_INIT(Init) method which initializes class by setting a class name with

and constructor (the “new” method) with:

Of course we need methods inside the class too:

Method static NAN_METHOD(New) is our constructor, but in JavaScript we have to take care also for the possibility of using the constructor without the new operator – we just call the constructor with provided arguments in that case. Also we have a static field to hold that constructor. There we use a trick to avoid initialization in another file – we don’t need this if it is static variable in static method, so we return a reference to that object:

Last but not least I will show you how we can create a method in the class, this time descriptions will be inline in code:

That’s all. I have tested callback with simple logger class (to log messages from the addon to JS console) and it works. There were no callback calls for scan, because my devices are not BLE.

Seems quite easy at this point, but believe me – it wasn’t. At least it is not when you don’t have a code that you can copy and paste or clone.

CoreBluetooth and bluetooth devices enumeration on OS X

So ending our adventure with first module – bluetooth devices enumeration I have bad news. OS X does not support programatically enumeration of generic Bluetooth devices. There is CoreBluetooth, but it works only with BLE (Bluetooth Low Energy). There is the GameKit, but it only works if you want to pair two or more devices with specified service type – in most cases iPhone with Mac. I wanted something like this:

So we have now a module that enumerates BLE devices nearby. And ELM327 is not a BLE device. GREAT 😀

Anyway, I have learned a lot about what is not possible and a lot about what is not. For new it will be enough to tell user to just connect the device before use. Whole prototype project is in this commit:

https://github.com/killpl/obd_cougar/commit/f2a2e32ef41cef369ac94a7e5e7bf3dad18df147

In directory prototypes. Next article (soon) will be more technical about module developement based on cougar_bluetooth_lib module.

Binding.gyp file for Objective-C++ project built using XCode

Hi!

Last time we started with the project and I promised that next will be an addon. I don’t have it finished yet, but stepped into an unknown teritory of configuring everything to compile and link find with an Objective-C(++) code and native macOS libraries: CoreBluetooth and CoreFoundation.

There are not many informations at all on the internet about how to make it work so I had to do a lot of guessing and trying.

First I made a rookie mistake (I am a newbie with Node addons so no surprise here) and added include_dirs at the wrong level of the file. Which made it unusable for both Xcode and node-gyp.

And I spent a few hours just setting it manually in Xcode settings (some of node-gyp commands remove the project file, node-gyp rebuild  for example, or just node-gyp clean ) before I found the problem.

I was really pissed off at the moment when I have found out that most of settings that I put there were just not parsed at all because there were not added as a child element of target.

Anyway.

We need to build on OS X using native libraries. I wanted to use Objective-C too just to try how it works. So first we may add .m and .mm files (.m is Objective-C, .mm is Objective-C++ – there is not much difference between them, second just allows C++ code inside) so my “sources” now looks like this:

Of course it won’t work now. We need to change at least two more things. First (this is not mandatory, but I really recommend that) we add conditional settings based on operating system. This way we will not break compile on another platforms in the future:

Then we populate the “mac”:

Notice how libraries are imported (“link_settings”). Somehow for one library it is:

It does not work for more than one though, tried using comma etc. The way I put it works.

Next thing is CLANG_CXX_LIBRARY which means I can use C++11 and -ObjC++ which tells the compiler that some of the code will be in Obj-C.

Now also project created with this command works and can be built using Xcode:

This works fine so I will now try to finish the library and add some logging possibility. Stay tuned 😉

Let’s start with C++ NodeJS addon

First things first – I know literally nothing about NodeJS C++ addons. I have an experience with C++ and with interopearation between C+++ and other languages, but not JavaScript and definitely not NodeJS (except small, top-secret project in bozon).

So we are going to learn together ;] Happy?

Let’s get started with getting project structure prepared – current architecture divides the project into (at least) three layers, which makes it kind of “Buissness Logic Desing Pattern”:

  • JavaScript / HTML presentation layer.
  • JS / NodeJS thin proxy as a business logic.
  • C++ addon for NodeJS for whole OBD2 protocol and connection.

The first layer has to run on desktop – which does not often happen for JS apps. That’s where Electron kicks in. It is a framework for building desktop apps with NodeJS, HTML and CSS, which nicely fits my needs.

Sometimes I am actually a lazy person and don’t like to create whole project structure by hand, so for that I’ve been using Bozon. It is not perfect, but creates a project scaffolding with build script, run script and unit testing script (created with Gulp, whatever this is). Exactly what I need, everything else I can do myself. You can see it created yourself in this commit.

Okay, enought about libraries, let’s start with creating NodeJS addon in C++, so we can see how it works.

First we create a source code of our binding layer file as described in documentation:

Then we have to create a binding.gyp describing build configuration:

At the end install and run the node-gyp:

Now we have a scaffolding for the C++ plugin which can be easily built. There is one more thing actuall, I don’t like writing C++ in the notepad, so I wanted to have an XCode project and this is quite easy to do with one command:

Clever. The build does not work without node-gyp configure ran after though.

Then we want nan module which creates an abstraction between v8 and node version and our C++ code. I wanted to do this myself, but there is no need to reinvent the wheel:

And change our bindings file, there should be added information about include directories:

Now every use of #include <node.h>  should be replaced with #inlcude <nan.h> .

Also if you use like me Xcode you need to edit project “binding.xcodeproj” and add to search paths nan directory:

Also we will in the future have more than one NodeJS library so we might want some common code – path to headers should be added the same way.

This is all for now, in next post we are going to try this with bluetooth enumeration on macOS and think about why node-gyp does not create proper project with HEADER_SEARCH_PATHS.