Friday, May 15, 2015

Johnny-five and node-red in a Docker container

Picking up where I've left off in my previous post, I tried to get the simple Blink 2 flow (bottom of the page) working inside a Docker container. And in the end I did, but I had to get over a couple issues first.

My first tries, nothing happened: every time when node-red would start, I see in the console "looking for connected device..." and that was it. Seeing that johnny-five would not connect and getting errors running the flow (cannot read property 'type' of null), I exited the container without stopping it as described in my previous post (Ctrl+PQ followed by Ctrl+C and docker exec -it mynodered /bin/bash), and tried to run the johnny-five board.js example app in node_modules/node-red/eg with:

node board.js

Again, "looking for connected device..." was displayed and nothing else happened no matter how long I waited. Wondering what could be wrong, I checked /sys/class/tty and indeed there was no ttyUSB0 there; I remembered then the --privileged docker run option mentioned in my previous post and in the Docker docs so I restarted the container using this command:

docker run -it -p 1880:1880 --privileged -v ~/my-node-red:/root/.node-red --name mynodered --rm claudiuo/node-red

Unfortunately this didn't change anything, same message showed up both when node-red and board.js started. ttyUSB0 was now present so I knew I was on the right track but still had no idea how to make things work. In a last attempt, I decided to modify board.js and specify the port explicitly as var board = new five.Board({ port: "/dev/ttyUSB0" }); as mentioned somewhere in the johnny-five docs and this time board.js connected to my Arduino and the LED on pin 13 started blinking. This was an awesome moment!

Next step was to modify settings.js and do the same thing, changing the default global context entry:

j5board:require("johnny-five").Board({repl:false})
to:
j5board:require("johnny-five").Board({port: "/dev/ttyUSB0", repl:false})

and restarting the Docker container this time I saw johnny-five connecting and the blink flow worked right away. I can't say I like this solution very much because ttyUSB0 may change on a different machine (or maybe even if I plug in my Arduino in a different USB port) but the fact that it works is awesome. (As a side note, not setting the port explicitly in settings.js works great with node-red outside Docker; not sure why this is the case). Now I need to take the next step and figure out how to use callbacks in a flow (callbacks are key to some of johnny-five functionality but luckily the awesome node-red team added them in node-red 0.10.6 as described here).

One cool thing that needs mentioned is that while I was searching the web for solutions to my issues, I found out a book about johnny-five was just published a few days ago on May 8: Make: JavaScript Robotics: Building NodeBots with Johnny-Five, Raspberry Pi, Arduino, and BeagleBone - I'm sure it is great and I will be getting it very soon.

1 comment:

Sandeep Dinesh said...

Thanks for the article, it really helped me with using Arduino with Docker!

With the latests Docker version (1.9) it looks like specifying the port in Johnny-Five is no longer required. I wrote a blog post here on doing very similar things on OSX, which unfortunately is more complicated: https://medium.com/google-cloud/developing-for-arduino-with-docker-and-johnny-five-on-osx-cc6813ae6e9d#.8p8hg2a8i