Writing automations using type-checked typescript

I like home assistant, but sometimes I have some automation ideas that are very annoying to implement using the GUI, and I wished I could write some code instead.

I’ve looked into AppDaemon, but coming from a JS background, it didn’t feel very natural to me. In JS, you usually will register event listeners, and you can do anything inside it.

link.addEventListener('click', () => {
   // ...
})

The entity and service names in HA can be quite long as well, so I wanted to have autocomplete while I type instead of copy-pasting from HA all the time.

So I wrote a library to let me do this. It uses some typescript tricks to autocomplete and type-check the entity IDs, services, and service params.

// This file is generated based on your instance
import ha from "./ha.js"; 

// Turn off lights once I put my phone in the wireless charger,
// but if I quickly pick it back up, turn it back on

const SWITCH_BACK_ON_TIME = 15 * 60 * 1000 // 15 mins
let lastTurnedOffLights = 0;

ha.onStateChange('binary_sensor.sm_s918b_is_charging', (state) => {
  if (state === 'on') {
    if (ha.getEntityState('switch.bedroom_lights') === 'on') {
      ha.callService('switch.turn_off', {}, { entity_id: 'switch.bedroom_lights' })
      lastTurnedOffLights = Date.now()
    }
  } else {
    if (ha.getEntityState('switch.bedroom_lights') === 'off') {
      if (Date.now() - lastTurnedOffLights < SWITCH_BACK_ON_TIME) {
        ha.callService('switch.turn_on', {}, { entity_id: 'switch.bedroom_lights' })
      }
    }
  }
})

I also added some helper functions, like checking the state of multiple entities at once.

import { multiPredicate } from "@isham/typed-home-assistant";

// Remind me to charge work test devices
const whenAtWork = multiPredicate(ha).with('person.isham', x => x === 'work')

whenAtWork.with('sensor.work_iphone_battery', x => x < 30).do(() => {
  ha.callService('notify.isham_s_telegram', { 
    message: 'Work iPhone battery low, charge it before you need it' 
  })
})

whenAtWork.with('sensor.work_android_battery', x => x < 30).do(() => {
  ha.callService('notify.isham_s_telegram', { 
    message: 'Work Android battery low, charge it before you need it' 
  })
})

// These automations trigger when I arrive and they're already low 
// OR if the battery drops while I'm there

You can try it out by following the quickstart guide in the GitHub repo: GitHub - ishamf/typed-home-assistant

Let me know what you think!