Use JavaScript for your automations

This is an external engine that exposes Home Assistant entities and services to JavaScript scripts. It works by connecting to HASS WebSocket API, and encapsulates all available entities as JS objects to be able to simply interact with them using JavaScript.

Scripts are constantly monitored in the scripts directory. They will be loaded when the service is started, reloaded when modified, and unloaded when deleted (also before reload).

JSON files will also be monitored and (re)loaded automatically. Scripts are notified when this happens. This provides a way to configure the scripts (and change their configuration on-the-fly), if your scripts want to support this.

Why

If you are used to JavaScript and do not want to go through the learning curve of Python and YAML templates (or just prefer JS for your automations), this comes to be a very handy tool that adds the capability to use JavaScript for your more complex automations, that may not be easily (or possible at all) implemented using templates.

After waiting for a proper JS integration and seeing that attempts were stalled for a long time, I decided to run my own one.

Installation and usage

Please refer to the github project page for details.

This is functional but still under development. Please let me know if you have some issues, including with the installation steps.

If you find it useful and give it a try, please let me know if you face some issues with the installation process. Of course, also glad to know if it works fine in different scenarios. :wink:

2 Likes

Ha! I had a similar idea myself! Although I went a little bit different direction with the api, and your runtime is more polished in general. I would not recommend anyone to use my project, but maybe someone will be inspired to continue the trend of js integrations)

Well, the topic itself seems to raise some interest :wink: at least if only by looking into the clones and activity on my github for an otherwise unadvertised project.

Happy to receive feedback on installation process and possible future enhancements.

I do not have an opinion about the use of this integration, but you should get your facts straight. Automations in Home Assistant have never been in Python, nor do you need any knowledge of it. Templates are not yaml, and you can write automations without templates or yaml using the automation editor. So the why just boils down to you like JavaScript better, which is fine by me.

2 Likes

Always a fan of projects like this. Python is my jam so i’m going to stick to Pyscript in HACS, but glad to see there’s options for those who prefer JS!

You are right: probably not the most accurate wording. It should have probably been ā€œfor those not wanting to go through the learning curve of HA templating and Python for complex automationsā€. :wink:

There’s a little bit more of reasoning for this than just than liking JS more than HA templating. Templating and HA automations are great, but sometimes you need more flexibility or a real programming language behind. This is where JS vs Python preference and learning curve comes into the topic.

1 Like

I understand the merits, but my neurodiverse brain is having a hard time with inaccuracies :slight_smile: I did some pretty complex stuff using templating (like charge the car at the time of the maximum predicted solar yield, optimizing charging speed and always ready before the next calendar appointment, with enough juice for the distance of the calendar location). So I can appreciate templating is not ideal for the harder stuff. It works, but it isn’t pretty.

Agreed.

I started doing some hard automations with templating and decided to switch to JS. As you say, complex automations with templates may be ugly and hard to maintain sometimes. Here is where being able to make automations in Python (or JS, for the present case) comes to be handy.

Apart, of course, from being able to interoperate with basically any existing library (Python or JS) in the world. Some automations are indeed programs, so better a programming language for those (my opinion, of course) :slight_smile:

If you happen to give it a try and run some JS scripting with this, and it works for you, please let me know :slight_smile:

2 Likes

Hi PuzzleStar,

Thank you so much for your work. It looks really good and I am eager to adopt it. Need to set up the right environment for it still. In the meantime, maybe my note here could help someone (like me before).

About a month back I started with HA and I was dismayed by the automation interfaces. I found the kettlepod thread early on (totally resonated), and of course your work. But I had barely started. I knew the HA concepts and had tinkered, but I wasn’t ready to go outside the box so soon.

It’s about a month later, and I have some pretty darn complicated automations going with almost pure JS code. I came up with mechanisms that work ok. I think this counts as a healthy stepping stone to adopting your work. For others new to the scene and want to just write JS … this is what I think would have helped me.

My setup:

  • HAOS install (anyone new definitely start with that).
  • Node-Red and the Node-Red companion

the rest is about how to use Node Red, such that you get close to an environment that FE developers would be ok with. Node Red has a learning curve but not that bad:

The key tips:

Emulate JS Modules (export and import):

  • use function nodes like JS modules. Define reusable code and use global.set() in place of export.
  • Likewise, use global.get() in place of import to pull code in.

So library code in a function node looks like this:

const { debug } = global.get('core');  // import a core routine

const lib = {
  add: (x, y) => {
    debug(`i'm adding ${x} and ${y}`);
    return x+y;
  },
  ...
};
global.set('lib', lib);  // export
return msg;    // you need this

Get those dependencies to run in the right order

You need to ensure dependencies run first. Don’t use ā€˜Setup’, ā€˜on Start’ or ā€˜On Stop’ in the function node. Have all code defined in the standard ā€˜On Message’ tab. You just set up an inject node to inject once after ā€œ0.1 secondsā€ (not 0). and tie your dependences together. If your dependency tree gets a little complicated like mine, use join nodes (set mode to manual, and ā€˜after a number of msg parts’ set to number of nodes it is listening to). See below for the picture.

Get console.log() working for you

Console.log is available. Debug nodes aren’t great. In HAOS, Node Red runs in a separate docker container but you can totally access the logs for it and tail in a terminal:

  • ā€œUse Advanced SSH & Web Terminalā€ Add On, with ā€˜Protection mode’ disabled
  • SSH to HA … and run ā€œdocker logs -f addon_a0d7b954_noderedā€ … it tails the console.log.

Like every better environment, wrap console.log so it spits out the date, the module the code is in etc.

Understand the limitations

You can do a lot with just JS code. You have access to the entire state of HA
(global.get(ā€˜homeassistant’)). But listening to state changes, and issuing commands/actions - best to do that with separate nodes. I mostly use just three:

  • inject node (interval)
  • events: state (listen to state change)
  • action node (to make changes)

For all the actions I form in JS code (just an object) and the action node I pass the object to and it sends it to HA. I don’t have to finangle with JSONata or anything like that. It’s a little annoying to have to figure it out these JSON structs, but chatgpt usually gets it right, and you can figure them out from the developer tools in HA. There’s a pattern to it and you build up your library for all the types of entities you need to control.

For more complicated things:

  • expose parameters in dashboards via HA helpers (input_number, input_boolean, schedule etc). Think of HA as your state and UI, and Node Red as automation.
  • store internal state in Node Red using global/flow/context. You can persist to disk (ā€˜file’ setting, ask chatgpt).
  • you can trigger and use all the HA things … AND … you have access to node red stuff too from the Node red community catalogue. I pulled in SunCalc JS code + doing math myself, but still installed ā€œthingzi-logic-timersā€ for sun timers cause it’s so convenient.

Some things I dislike which makes me want to switch away:

  • No typescript, no code completion/understanding of code outside the immediate function node. So it is easy to make typos and harder to maintain.
  • No version control.
  • The editing isn’t bad. I got tab size to 2 spaces (took some searching) and multi-line editing is there (VScode editor under the hood). But it’s limited.
  • If you open multiple browser windows so you can look at code in one function node while editing another, it can get hairy with those getting out of sync with each other. You have to be careful not to lose changes.

Hope this helps.

  • Glen
1 Like

Hi @thebayleyfam ,

Thanks for your comments. In my opinion, this is probably too much if you just want to integrate JS automations (just my opinion, of course).

I know indeed several people using Node-Red, and after speking to them, I decided I just wanted to keep away from setting up some components I do not really need just to get some JS integration, so that’s why I developed my ā€œpure-hass-javascript-engineā€ (this one :wink: ).

I do find much more simple something like (of course, this is a very dummy example…):

"use strict";

module.exports = {
        'entity-{switch.my_dummy_switch}-state-changed-to-{on}': function (id, state, old_state, entity, old_entity) {
                JSEngine.Entities['light.my_dummy_light'].turn_on();
        },
        'entity-{switch.my_dummy_switch}-state-changed-to-{off}': function (id, state, old_state, entity, old_entity) {
                JSEngine.Entities['light.my_dummy_light'].turn_off();
        },
}

This runs nearly out of the box with my JS engine (only need to set-up credentials to access HASS), which exposes all entity available actions as direct methods for every entity object.

Please let me know if you finally use it and get it working. It should be pretty musch simpler than using Node-Red just for running JS scripts.

Happy to see something like this!

I will try it in the next days. I have no will of picking up again the YAML/Templating/Jinja/NodeRED/JsoNata extravaganza once more in my life :sweat:

I’d also be happy to support with development should you need a hand :smiling_face:

Thanks, Salvatore,

Please let me know if it works OK for you or whether there is something I should check / fix.