Openhab automations JS library

In the broad sense, an automation is an algorithm that takes data from some Items and derives the state of others: e.g., controlling ventilation by CO₂, lights by time of day, heating by temperature, etc.

After building a number of such automations, I realized what I don’t like:

  1. Automations ignore manual changes to the controlled element. You might control lighting by time of day, but there will be moments when you want to turn it off at night or on during the day manually.
  2. Sometimes you need to quickly toggle specific automations off and back on—not all of them at once. For example, you have an automation regulating ventilation, but guests arrive and they feel a draft. You also want a quick overview of what is currently enabled/disabled.
  3. A disabled automation ≠ no automation. I decided the system should bring me back into the automated state once the situation changes.
  4. Most automation algorithms look template-like: when something changes or on an interval, change something else, possibly checking a short retrospective window (the last N minutes).

In one “factory” system (unfortunately I don’t recall which) I saw a very simple, clear, and elegant approach: a three-state switch for each automation — enabled / disabled / disabled for a duration. A manual change of the controlled element simply disables the corresponding automation for a set time, after which it automatically returns to the working state. You can also fully enable or disable an automation manually.

For a while I built such a switch for each automation by hand; it was tedious and a lot of boilerplate. Then I created a dedicated JS library, “automator”, and battle-tested it. I now consider it stable and useful beyond my own setup - openhab-automator on npm.

How it works (example from the docs)

Say you want to automate turning on the kitchen light if there’s motion and it’s dark.

The example below (described in words) demonstrates most features, many of which are optional:

const automator = require('openhab-automator');

// Create an automator for the kitchen light
const m = automator.for('Kitchen_Light')
  .label('Kitchen Light — Auto', 'Kitchen')
  // Custom options (minutes -> label)
  .options({ 
    '2': '2 min OFF',
    '120': '2 h OFF'
  }, '2')                 // default manual OFF duration (minutes)
  .onActivate(() => {
    console.log('Kitchen auto: ON');
  })
  .onDisable(() => {
    console.log('Kitchen auto: OFF');
  });

// Logic: turn on if there is motion and it’s dark; turn off if no motion
m.handler(function (event) {
  const motion = this.Kitchen_Motion;
  const lux = this.Kitchen_Lux_average_5m; // persistence average over 5 minutes
  if (motion && lux < 50) return true;     // ON for Switch
  if (!motion) return false;               // OFF
})
  .dependsOf('Kitchen_Motion', 'Kitchen_Lux') // declare dependencies
  .debounce(15)                               // soft debounce 15 s
  .interval(60);                              // check every minute
  • If there is motion and the average illuminance over the last 5 minutes is < 50 lx, turn the light on; if illuminance rises above the threshold, turn it off. (As an example only—yes, the logic is simplistic.)

  • The automation is evaluated on lighting changes, motion changes, or every 60 seconds (because we use a 5-minute average), with a soft debounce of 15 s so it won’t “flicker”.

  • If you manually toggle the kitchen light, the automation pauses for 2 minutes.

  • I often use the automation’s onActivate / onDisable events to send messages to the logs and/or to our home Telegram notifications.

1 Like

You need to be careful with the naming here. The name “openHAB” is a registered trademark. You need to get explicit permission to use it in the name for your library. I was given permission to use it in mine way back when mainly because I started using the name before the trademark was registered and already had a large user base. But even then, I needed to get permission.

See Trademark Policy.

Otherwise, this looks like a great addition to the community. Thanks for posting!

1 Like

Hmm, thanks for the information - I’ll look into it. The issue is that we need a way to clearly indicate that the library works only within the OH ecosystem, since it’s published on npm.

I would recommend to put it into a special namespace in npm, so it’s clear it belongs to something else than openHAB but refers to openHAB.
Take for example my library:
https://www.npmjs.com/package/@hotzware/openhab-tools

Apart from the trademark stuff:
Looks really nice, if my KNX actuators wouldn’t already have automation integrated I would have plenty of use case for it.

2 Likes

I’m not very familiar with the JS world - I’m more of a backend engineer ). What do you mean by a namespace in npm? I looked at your package, it structure looks very similar to mine, except that it’s in TypeScript. Could you point me in the right direction?

The namespace is the @hotzware part of the full package name.
Actually it’s called scope, see About scopes | npm Docs.
The full package name is scope + openhab-tools.
So this has nothing to do with the structure of the package, you just need to have a scope and change the name field in package.json to @scope/name.
See Creating and publishing scoped public packages | npm Docs.

I have my personal npm account and then the @hotzware organisation.

Think of npm scopes like the groupId for a maven artefact.

1 Like

Got it. I’ll take care of it.

That’s the path I was headed down when I thought I was going to have to change the name of the repo.