Building automations in Typescript with @digital-alchemy

Hey y’all!
I wanted to introduce my project @digital-alchemy. You can think of this as an alternative to NodeRED, PyScript, and YAML/other traditional automations. The focus of this project is to allow the creation of automations for Home Assistant using more traditional NodeJS/Typescript based code.

This guide is intended to be a condensed introduction, providing a brief overview of the project, and linking off to external docs for deeper dives.

Repo Docs Description
core link Wiring, configuration, boilerplate utils
hass link Friendly API bindings for home assistant
synapse link Entity creation tools (typescript side)
synapse-extension link Entity creation tools (custom component)
type-writer link Script for translating your setup into Typescript types
automation-quickstart link Starting point repo for getting your own thing started

Overview

The project doesn’t have any special editor plugins, ai tools, or special environment needs. Just have node20 installed, and it’s good to go!

It is all Typescript trickery and a basic websocket connection on the inside. Use whatever method of running you want; pm2, docker, inside a tmux window, just straight up dev server in watch mode, whatever makes you happy.

For those who are running a HAOS setup, like myself, the quickstart project will provide you with an addon to run the code in. Allowing you to keep all the logic for your setup inside the config folder.

For the how side of things, the hass library has a set of generic apis that can be fitted with data from type-writer to provide specific details about your setup from within your editor. The script can be run at any time to give you more up to date editor definitions.

Quickstart Script

This is intended for HAOS setups

This command will utilize the setup.sh script stored within the quickstart repo to pull down the rest of the project, then set up a nodejs environment inside the Code Server addon, and finally place the code runner addon in your local addons.

curl -fsSL https://setup.digital-alchemy.app -o setup.sh; bash setup.sh
  • Quickstart setup
    • A quick overview of the automation quickstart project, with videos demonstrating how to set it up, and what the editing experience using the library
  • Quickstart orientation
    • Next steps guide / deeper dive into the quickstart project. How to make the project go, what’s important to know, etc

Sample Automation

To give a tiny code demo, this is a minimal automation that listen for events, and issue switch toggle calls.

import { TServiceParams } from "@digital-alchemy/core";

export function BasicAutomation({ hass, logger }: TServiceParams) {
  const mySensor = hass.entity.byId("binary_sensor.my_example_sensor");

  mySensor.onUpdate(async (new_state, old_state) => {
    logger.info(
      `my_example_sensor updated ${old_state.state} => ${new_state.state}`,
    );
    await hass.call.switch.toggle({
      entity_id: "switch.example_switch",
    });
  });
}

Typescript will validate / suggest entity ids, and provide information about the shape of the entities that get returned. What attributes they have, that sort of thing.
The hass.call will contain all your available services, along with type definitions to help suggest parameters.

Project State

Don’t be deceived by the short git history, the project has been under off and on prototyping and development since early 2021. It’s been a side / passion project until this year, when I took to resolving the major tech debt and building project docs.

There’s still a lot of enhancements and cool ideas left to implement on the road to extracting maximum value from your setup for the editing experience, and I’m open to contributions of all sorts on the project. I’m easiest to reach via Discord

3 Likes

This looks very interesting. Are there any examples around how to write test driven automations? Like mocking/stubbing the home assistant api?

Thx

Nothing finalized yet, I’m part way through building a library that would be up to the task. It’ll work by putting up a putting up a websocket server for the regular hass library to connect to, and have some functions to emit entity updates, track service calls, and stuff like that.

Need to also make sure that my scheduler play nice the tests, but should have that all documented in a couple of weeks. It’s definitely one of my higher priority items

2 Likes

New feature as part of April updates

The hass library has gained the ability to directly work with:

  • zones
  • floors
  • areas
  • labels

You can create, update, apply, remove, etc these across your system. There are also new quick querying APIs for quickly calling services using these groups. Optionally filtering by domain with.

export function Example({ hass }: TServiceParams) {
  const exampleSensor = hass.entity.byId("binary_sensor.example");
  exampleSensor.onUpdate(async () => {
    if (exampleSensor.state === "off") {
      await hass.call.switch.turn_off({
        entity_id: hass.entity.byArea("living_room", "switch"),
      });
      await hass.call.homeassistant.turn_off({
        entity_id: hass.entity.byFloor("downstairs")
      });
    } else {
      await hass.call.light.turn_on({
        entity_id: hass.entity.byLabel("my_special_label", "light"),
      });
    }
  });
}

Just like with entities, all your labels / areas / etc will have typescript suggestions & validations right in the editor.

1 Like