Using npm modules in transformations (and humanized duration example)

being the kind of person I am, I decided that instead of doing the easy thing and just rolling my own javascript function, I wanted to make my life far too complicated and figure out how to use npm modules in my javascript scripts for openhab.

I ended up using https://github.com/nodyn/jvm-npm which, after a little playing around with paths (cwd is apparently not /etc/openhab2/transformations when executing transformations) it worked pretty much immediately for moment.js.

The first thing to do is to take the content from https://raw.githubusercontent.com/nodyn/jvm-npm/master/src/main/javascript/jvm-npm.js and paste that into /etc/openhab2/transformations/jvm-npm.js - this is the core file which allows you to include npm modules.

At the top of the script you want to use the module in, you now need to load the jvm-npm file as such:

load("/etc/openhab2/transform/jvm-npm.js");

In my example I wanted to use moment.js, so the next step is to actually download the module. Whilst in the /etc/openhab2/transform folder run npm install moment to install it (if the npm command isn’t found, install it with apt install npm).

This is where things diverge a little from the standard npm workflow. Usually you could just do var moment = require('moment') to include moment in your script. That won’t work here though, as the working directories aren’t correct. Instead, we need to give the full path to the module:

var moment = require("/etc/openhab2/transform/node_modules/moment/moment");

Now that we’ve got moment installed and loaded in javascript, we can use it in our script. Below is a full example of a script to turn uptime in seconds into a human timestamp (e.g. “20 minutes”, “5 days”, etc…):

load("/etc/openhab2/transform/jvm-npm.js");

var moment = require("/etc/openhab2/transform/node_modules/moment/moment");

(function(seconds) {
  var now = moment();
  var upsince = moment().subtract(seconds, 'seconds');

  var difference = now - upsince;
  return moment.duration(now.diff(upsince)).humanize();
})(input)

Some modules that require browser or node.js specific functions still will not work. I haven’t come across such an example yet, but including something like this js file may help:

var global = this;
var window = this;
var process = {env:{}};

var console = {};
console.debug = print;
console.log = print;
console.warn = print;
console.error = print;

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.