Installing Nodejs and node-hid on a Raspberry Pi armv7+

I have done quite a few projects now using the node-hid library with Nodejs. It does require a little work to get up and running on a Raspberry Pi but it is well worth it. In this post I am going to cover the steps for getting it running on a PI mainly to self document as I am forever having to work this out every time I need it. If I used it everyday I would probably remember the steps but it's just long enough between installs that I forget the steps I take. I may come back to this post and edit it from time to time to ensure its correct as I find issues.

What does node-hid do?

Node-hid allows you to access USB HID devices from Nodejs projects. This as you might imagine is very handy. Joysticks, mice, keyboards, busylights to name a few but basically anything you can stick into your USB port that supports the HID standard.

https://github.com/node-hid/node-hid

Below are basic step by step instructions on everything from installing the image on the Pi and installing node to getting node-hid onboard. This is very basic guidance especially the initial installing the OS and node. If you want screenshots and all the rest go to here.

Installing OS on Pi

Step 1. Download Pi Image
https://www.raspberrypi.org/downloads/raspbian/
Step 2. Use Etcher to place image on SD card:

This is a great tool recommended by raspberrypi.org.
 https://www.balena.io/etcher/

Prepare Pi

Step 1. Upgrade Pi:
$ sudo apt-get update
Step 2. Update packages:
$ sudo apt-get dist-upgrade

Installing Nodejs on Pi armv7+ (This will not work for armv6 Pi's)

Check your Pi version using:
$ uname -m
 Step 1.  Updates Debian apt package repository to include the NodeSource packages:
$ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
Step 2. Install
 $ sudo apt install -y nodejs 
Step 3. Check node version
$ node -V

Installing node-HID on a Pi

Step 1. Install tools:
Linux (kernel 2.6+) :
  • Compilation tools: $ sudo apt install build-essential git
  • gcc-4.8+: $ sudo apt install gcc-4.8 g++-4.8 && export CXX=g++-4.8 (note: not sure how applicable this is)
  • libusb-1.0-0 w/headers: $ sudo apt install libusb-1.0-0 libusb-1.0-0-dev (note: possibly already installed)
  • libudev-dev: $ sudo apt install libudev-dev
 Step 2. Compile:
$ npm install node-hid --build-from-source
 Step 3. Move on to building/installing application

VoIPNorm


CE SIP Messaging Channel for Remote Endpoint Control

Sending messages between endpoints over SIP seems so 2010. If you look at this feature on the surface it does seem limited. It is once you enable it with Macros or an xAPI application does it potential use become more apparent. "xCommand Call FarEndMessage Send" does not get a lot of coverage in discussions online , in fact I was unable to locate a single article even explaining its use but it is a very handy API command worthy of understanding. Here are some of the feature uses I was able to dream up but I am sure there are others:
  • Far end camera control, volume control, and mute control. Anything on the remote endpoint that can be controlled or set by xAPI commands.
  • Control far end external devices such as far end HDMI switch using macros with http commands. You could even adjust lights and blinds etc using this method if they are integrated with the remote codec.

Configuring SIP Messages

By now I am pretty sure most of you understand the theory behind a point to point call with a established call control platform like Communications Manager(CUCM). In my examples I am going to ignore the basics and focus on once the call once it is established. This configuration only works for point to point calls.



Once a call is established, if the endpoint is enabled it can send and receive custom SIP messages. Below is a great macro example of being able to control a camera via this method. If FECC natively works this is overkill but some 3rd party camera do have issues with native FECC control like the Sony SRG300HD.

I have not included the UI controls in the example. So you will have to build a Touch 10 UI that matches up with the valid input required by the macro. The important part of the example is the way in which the SIP message commands are used. The example macro is loaded on both endpoints of a p2p setup and allows both endpoints to control each others camera.


There are two ways to send the messages across the SIP channel using either a macro running on the local CE endpoint or from a application connecting to the local device utilizing  xAPI commands. I personally have done this using a Pi running nodejs sending commands to a Webex Room Kit to send commands to a SX80 to control the camera. The dependency is the remote end must have a macro/application to receive the messages and translate the messages into a action with xAPI.

Key commands for enabling SIP messaging:

Send: xapi.command('Call FarEndMessage Send', { Your command goes here})

Receive: xapi.event.on('FarEndMessage Receive', (event) => {
//Do something with your command })

Enable: xapi.config.set('Conference FarendMessage Mode', 'On')

Nothing to hard and with a lot of potential.

VoIPNorm

Upcoming Topics on VoIPNorm

Here are some upcoming topics I am working on for the blog. If you would like to see a discussion on other features and items please let me know in the comments below.
VoIPNorm

Part 4: Webex Board + Rasp Pi + BlyncLight = Final Project

Project Intro Recap

For a project that I thought would only take me a few hours it was way more intense that I first intended it to be. If your not familiar with the project, here is a quick diagram of what I was aiming to do.
Basically, if my Webex Board is on a call turn the Blynclight from green to red. Once the call is over turn it back to green. It seemed pretty simple and straightforward.

Step 1. Acquire BlyncLight(BL) + Pi + CE Room systems

This was the easy part. Buying the pieces from Amazon that I didn't already own. In my case it was just the Blynclight. I already had some unused Pi's and also a very well used Webex Board in my office. I purchased the wifi version of the BL. My thought was I would probably need this so I can locate the light outside my office in a highly visible place. 


Can't get more visible than this. This is the working BL fully installed.

Step 2. Build Code using Python not Nodejs

This is where the real adventure begins. Not knowing that the manufacture, Enbrava, has since changed the BL's command word, vendor id and product id in the latest hardware release, nothing already existing from a Nodejs point of view was going to work. While the vendor id and product id are easily obtainable the command word is not and had to come from the manufacturer. After several email exchanges with them I resided myself to, "Nodejs is not going to work". 

Embrava who make the BL only support the use of a Objective C SDK and they do not seem to be all that willing to release the details of the command word to control the light. Their last response to me was, "We understand your concerns and thats why I have told you that I will try to get the approval to share the device protocol to you." The bolding was in the email BTW. This was my queue to start looking elsewhere for answers. Could I have used their SDK? I suppose but it seemed like an extra layer of messing around that I didn't want.

Python to the Rescue

While my efforts to get somewhere with Embrava fell short I did manage to find a great Python library. While I have never coded in Python before (outside of "hello world") I thought what the hell, I got this.

The code I had to write for the project was pretty simple. The application is monitoring the call status of my Webex Board using a websocket to communicate and posting events on call status to change the light color. 


The code was the easiest part of the project besides going online to purchase the BL from Amazon. Once I got the hang of working with Lists and Dicts in Python the rest was just adding the logic for turning the light on and off. Easy. I was surprised at the lack of code I had to actually write, although this is not a complex coding project it still surprised me.

Python libraries used in the project:
  • Python library for connecting to a Cisco Collaboration Endpoint using a WebSocket https://github.com/cisco-ce/pyxows . Just be aware the example in the readme has some issues and does not work without some fixing and additional code. 
  • Python BlyncLight library https://pypi.org/project/blynclight/ . The reference to HIDAPI could be a little better but still the library functions great and without it I wouldn't been able to get anything working. I am not sure how he got the command word figured out but credit to him for getting it done.

Step 3. Prep Pi for Python 3.7 and Load Drivers

At one stage I almost considered throwing in the towel at this step. The BL project would be residing in the pile of junk I keep in my office. I call that pile "the to do pile". Thank heavens for people posting stuff on the Internet. It really saved the project and me the embarrassment of telling my wife I paid $85 for something I can't use or figure out.

The first issue, a pip ssl error that kept saying, "pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available".  This was especially annoying as everything I tried failed. I finally stumbled on the blog post below by Josh.

Second issue was reading the USB port on the Pi. It was just not working with the HIDAPI module. This was resolved with some help by a KB article on setting up the HIDAPI module with more clearly defined instructions. The README from the library on github is a little cryptic when it comes to the install instructions for Linux.

Referenced links:
 

Step 4. Stand back and Marvel at My Functional BlyncLight


Even Lord Vader approves.

Project Outcomes

The project was fun despite some struggles.Two things I got out of this is firstly I really enjoyed was writing blog posts again and secondly using Python in a real project. It's been fun doing the updates as I go. While it takes time to do its a nice way to record the project. If I ever have to I can retrace my own steps. While I may never do the BL project again at least it's here if I change my mind. 

I hate learning a new language or scripting and having to step through the whole "hello world" crap every time. Learning really accelerates when you do real world versus lab world. So doing a Python project that applied to real world, although limited to my office, was a lot of fun. It has me thinking about what else I can do with some more Python skills. 

BlyncLight Thoughts and Conclusions

Would I buy a Embrava Wifi Blynclight to put outside every conference room in a company, no. The wifi versions battery life is less than optimal, seems to be about a day. I didn't want to have to charge the thing almost daily. I was also not impressed by the response from their support people. To only have the one SDK and not provide the command word is not what I would have expected. 

The BL was what I considered expensive. Now, if you were buying hundreds of these sure it would be cheaper but the $85 I paid was way to much. So while this was fun to mess around with and there are pieces of the project to learn from, there are more than likely better lighting systems to integrate with than this. I am sure if you want some off the shelf light that works with Jabber, S4B etc. that sits on your cubicle wall this would be great but for this type of project, it's only average. I would also recommend the much cheaper Standard BlyncLight and just use a USB cable if you decide to do this project or something similar.

Hope you enjoyed the project. Let me know what you think in the comments. Comment if you did a project like this you enjoyed or not.

VoIPNorm

Part 3:

Part 3: Webex Board + Rasp Pi + BlyncLight = Pi Driver Nightmare

It's been a rough few days with sleepless nights and hair pulling as I navigate setting up Python 3.7 on a Raspberry Pi. After messing with several different methods of installing Python and PIP only to end up with a PIP SSL error I stumbled upon a blog post by Josh which actually worked. At a high level, you have to download and compile the Python and SSL libraries so that Python actually knows where to locate the SSL library. I didn't see the SSL issue with other versions of Python but this seemed to be a very common issue with 3.7. I tried a number of solutions and Josh's was the only one that worked.

After solving the SSL issue I started putting my project together only to find that HIDAPI Python library was having issues reading the USB device. Rebooting the Pi seemed to do the trick. The HIDAPI library relies on libusb-1.0 which is a C library that gives applications easy access to USB devices. Why this reboot was required to make it work I am not sure but I also looked at another  article which referenced other USB drivers along with HIDAPI that was helpful to understanding how to install the HIDAPI library on the Pi.

I think this section of the project has consumed the most time. Even more so than writing the code for the project itself. It seem to take forever to get the Pi setup to run the code. Not that I haven't run into similar issues with Pi and Nodejs reading USB devices but its still painful to deal with when it happens.

Later this week I will write up a full post on the project with code.

VoIPNorm

Previous posts:

Intro to project:
https://voipnorm.blogspot.com/2019/07/webex-board-rasp-pi-blynclight-no.html

Part 1:
https://voipnorm.blogspot.com/2019/07/part-1-webex-board-rasp-pi-blynclight.html

Part 2:
https://voipnorm.blogspot.com/2019/07/part-2-webex-board-rasp-pi-blynclight.html

Part 2: Webex Board + Rasp Pi + BlyncLight = Python Dicts and Lists

So following on from part 1, today was spent going through Python tutorials on dealing with dictionaries and lists and how to create actions with the feedback data from a Collaboration endpoint. While I ended up with a working solution I am sure it is nowhere near optimal. Searching for a nested value in a dictionary that is in a list which has another dictionary had it complications. I managed to narrow down call status get events to:

{'Status': {'Call': [{'id': 53, 'Status': 'Connected'}]}}

Below is part of my solution for dealing with nested endpoint response:


Feel free to suggest improvements to the code in the comments below. Let us call my solution so far crude but effective. Obviously this is not all of it but I will present the rest when I am done.

Finally today I have started preparing my Pi to run my new Python code. This is a very useful tutorial on get your Pi running the right version of Python 3.7.

VoIPNorm

Part 1: Webex Board + Rasp Pi + BlyncLight = No Code

This is the first update as I explore building a new app to integrate a BlyncLight to a Webex Board.

Day one has been a bit of a bust really. While I have at least certified I have a working BlyncLight this has turned out to be much harder than I first envisioned. While looking into this project I did  look online to see if people had used Nodejs with BlyncLight before and indeed they had. While this is valid code for older BlyncLights, newer updated lights have since changed the 9 byte command word used to operate the light. This seems pretty straight forward but this command word description is not something the BlyncLight people just hand out.

The only SDK officially supported is written in Objective C and while there are probably quite a few of you that might be comfortable in the world of C I am not one of them. I did however find a nice Python library that seems to work pretty well. I did try to reverse engineer this library a bit to see if I could at least make headway working out what the command word should be but it was to no avail.

So my new task is now to learn Python and create an application worthy of gracing the pages of this fine blog. If the BlyncLight support people get back to me with the command word I will also try to make a Nodejs version of this application as well.

To date I have managed learn enough Python to:

  • Turn the light on and off
  • Change the light color
  • Use a CE library to create a websocket for feedback from a CE endpoint.
All-in-all not to bad, but I was expecting to have the first run of code already done. Still I stay committed to have something done in at least one language. If all goes poo poo my last resort is to learn Objective C and use the SDK but lets hope it doesn't come to that.

VoIPNorm

Webex Board + Rasp Pi + BlyncLight = No Interruptions

My new BlyncLight arrived today. My plan is to build a app using Nodejs to integrate BlyncLight with a Webex Board. Once complete my wife will know when I am on a call and to not come into my office.  That's the hope anyway.



I will provide updates with the steps I followed to make it work over the coming days.

This should be fun.

VoIPNorm

CE WebSocket v SSH v HttpFeedback. Which is Best?

I thought this would be an interesting comparison to write code for all three different connection types in their most simplistic form and do a comparison. Cisco collaboration endpoints now have three main methods to get data from an endpoint over the network ( I am not talking about a serial connection) for the purposes of interacting with the endpoints API. They are WebSocket, SSH and HttpFeedback. The example I am using in my comparisons is based on a very simple idea of I want audio status changes to be pushed to my server from the collaboration endpoint. In my examples I am using a Webex Room Kit to send commands to. If you don't know what that is stop reading now this post is not for you.

I am a part time Nodejs developer (I think so, so to hell with everyone else) so all the examples I am going to post will be in JavaScript. I am not the most elegant of developers though. I basically create stuff that works for the purposes of prototypes so don't expect JS ninja magic. My examples are good enough though for most to get the idea of what the hell is going on.

Lets get on with it....

Webhooks

This example comes to us from Magnus's Cisco Community Post.

Magnus created a nice clean Node example, so I am going to rip it right off of him.


A couple of things of note. This example uses two main libraries, JSxAPI and ws (WebSocket) libraries both of which are on NPM. Its a simple setup and responses from the endpoint are very quick. What I love about WebSockets is that you can use it over port 80 or 443 and using the WS library makes coding your WebSockets install very easy and clean.

There are however some considerations to make. If you are scaling out you application, just like SSH which I will get into in a minute, you now have to start thinking about how do I manage persistent connections potentially across multiple servers. Running everything on a single server should be pretty easy but on multiple servers connecting to a database can be much more difficult depending on what your trying to achieve. In saying that most use cases for using the API on a collaboration endpoint usually only requires to scale to just a few hundred endpoints or less which a single Nodejs server will easily handle.

An important point which also applies to SSH is how much chatter will there be from your endpoints. If you a monitoring a lot of events and status which causes a constant stream of communication your scale will ultimately be diminished. A single server can comfortable handle thousands of WebSocket connections if they are relativity idle most of the time but if your chatter from every endpoint is high then this brings down the amount of concurrent connections and something to monitor as you scale.

SSH

Talk about simple brah! SSH is even simpler from a coding standpoint as the JSxAPI library has the SSH2 library as a dependency you can just launch and control the session using the JSxAPI library.


While having an SSH library as a dependency is helpful at time this can be a little bit of a hindrance as well. If things go wrong you have to pull the covers back a little to explore how the two libraries work together and generally I have found scaling this out to anything beyond a 100 endpoints is more bother than it's worth. Connection failures, dropped connections etc etc just become a pain to deal with once you start connecting to an 1000 endpoints using SSH. Managing the connection state does have some benefits though.

If you know your connected SSH state then you don't have to poll your endpoints to check their state for at least the network connectivity. Event messages and responses are generally fast and there is little code required to create the connection. I have used this method many times when I have a single endpoint I need some form of app or controller to connect to it. My CE-Deploy app is a great example where I have used this method. I only need to connect to one endpoint at a time and the connection gets closed once the work is done to move onto configuring the next endpoint. Its simple and effective.

HttpFeedback

This is the most complex of the three to code but can be the most flexible and scalable. I say this because there is no persistent connection to maintain or monitor. It follows the typical HTTP pattern of request, response and done from a TCP connection standpoint.


If you can excuse some sloppy code (yeah yeah its not perfect) you will see that I used Express to help create a simple web server. I got a little help from a TP client library I use sometimes to help post my XML although this could have been simply done using the request module as well just a little more code. There are lots of options using HttpFeedback as the underlying code listening to the feedback messages is just a web server. The most difficult piece is configuring the client/endpoint to send the events and status updates to the server to start with. You have to let you endpoint know your server URI so it knows where to send its events and this is done using a XML message you can see in the code.

Another complex piece not shown is responding to an event like a user pushing to a button on the touch 10.  Just like registering feedback you now have to create your XML response to tell the codec what to do next. Plus since you are not maintaining a persistent connection how do you know if you should send your endpoint any commands you may need it to carry out. Say at midnight you want all endpoints to reset a setting to your default. this can be done by sending them a XML message to the XML API. With a persistent connection you might be able to work this out pretty simply but now you don't have that. Do you poll the endpoint regularly to check or just hope that it eventually comes back online and everything rights itself? What if you bring you app online and an endpoint is offline, how do you let your endpoint know when it comes online where to send its data. Some of this can be solved using TMS or a management platform but what if this is your own homegrown TMS? This method can be lots of work.

To Sum Up...

There are loads of great API's to work with once you connected to your endpoint and depending on your requirements one connection method might work better than another. For myself, I think for smaller to mid sized projects WebSockets is where I will spend most of my time and for larger projects, well, I will just try to avoid those for now at least :)

Hope you enjoyed the post.

VoIPNorm

CE-Deploy for Cisco Collaboration Endpoints

This is a on-going project I have been working on for a while. Originally I created CE-Deploy to just deploy macros to multiple Cisco collaboration endpoints but once I published the first builds I got a number of requests to add more features. 

CE-Deploy has the following deployment options:

  • Wallpapers
  • Macro Files
  • Touch 10 UI controls
  • Download logs for troubleshooting
  • Digital Signage
  • Branding
  • Webex Board Touch 10 enablement
  • Admin password update


It doesn't aim to replace TMS, Control Hub or CUCM management but targets certain things that are difficult to do on these platforms or are not available.

Check out the video demo here:



If you would like to contribute or  create a build for your OS the code is available on Github below:

https://github.com/voipnorm/InRoom-Macro-Deployer

To find out more about CE-Deploy there is a Webex Teams space available for feedback and request access to builds:

https://eurl.io/#SJWfk6qUV

This link requires you to sign up for Webex Teams to have access to the space, you have been notified!

VoIPNorm

VoIPNorm where have you been, again?

It has been a while since I last posted on my blog. I like this forum I was not sure that many people still pay attention to blogs. Seems like twitter, vlogs and you name your social media have taken its place but then I realized how often I still read other people’s blogs. While the material in my blog is a little different than it used to be hopefully it’s still of value to people that follow.

The number of people doing xAPI development for Cisco collaboration endpoints has certainly grown over the last 12 months so hopefully I can help provide some ideas and with all the new features coming in CE9.x there is no shortage of material.

If you have any questions or ideas for topics, please comment below.

VoIPNorm
-->