Coder Social home page Coder Social logo

abogaart / hass-sidecar Goto Github PK

View Code? Open in Web Editor NEW

This project forked from d4nicoder/hass-sidecar

0.0 0.0 0.0 161 KB

Homeassistant sidecar app to allow you to write home automations in typescript in a simple way

License: MIT License

TypeScript 99.52% Dockerfile 0.48%

hass-sidecar's Introduction

CodeFactor

Home assistant sidecar

Description

This is an app written in Typescript and NodeJS to interact with your Home Assistant installation. It manages the websocket and the MQTT connections with your host(s), and you can write your own automations in typescript in a simple way.

All automations are hotloaded, so you can create, modify and delete automations and they will be unloaded and loaded on the fly, without reboot the app.

Why

Home Assistant is a great platform to manage our smart devices, but for me the automations system is not entirely powerful, and on many occasions I need to do more complex things that I cannot do with a simple yaml or with the web interface. I love typescript and NodeJS and it is faster for me to write automations in this environment.

Getting started

For detailed information about classes and methods, go to docs/globals.md

To run the app, we need to connect to the websocket API of Home Assistant and to a MQTT broker. The values of these connections are provided by environment variables. The variables are:

  • HA_HOST: The address of your Home Assistant installation.
    • Example: 192.168.1.17:8123 or homeassistant.local:8123
  • HA_TOKEN: The token provided by Home Assistant to connect to the websocket API.
    • You can get it from your profile page in Home Assistant, in the Long-Lived Access Tokens section.
    • It is recommended to create a new token for this app.
  • MQTT_URI: The URI of your MQTT broker.
    • You need to enable the MQTT integration in Home Assistant, see https://www.home-assistant.io/integrations/mqtt/ for more information.
    • You can use the Mosquitto broker or any other MQTT broker.
    • The value is defined as: mqtt://user:pass@server:port
      • user - The user to connect to the broker
      • pass - The password to connect to the broker
      • server - The address of the broker
      • port - The port of the broker
        • If you are using the Mosquitto broker, the default port is 1883

Installation

> NodeJS version

# Clone the repo
git clone [email protected]:d4nicoder/hass-sidecar
# Change directory
cd hass-sidecar
# Install dependencies
npm ci

> Docker run version

docker run \
  -e HA_HOST=<your-host> \
  -e HA_TOKEN=<token> \
  -e MQTT_URI=<mqtt-uri> \
  -v <path/to/your/automations/folder>:/opt/app/src/automations \
  --restart=unless-stopped \
  danitetus/hass-sidecar:latest

> Docker compose version

version: '3'
services:
  hass-sidecar:
    image: danitetus/hass-sidecar:latest
    environment:
      HA_HOST: <home-assistant-host>
      HA_TOKEN: <home-assistant-token>
      MQTT_URI: <mqtt-uri>
    volumes:
      - <path/to/your/automations/folder>:/opt/app/src/automations
    restart: unless-stopped

NodeJS Dependencies

You can install dependencies directly with npm (on native installations) or in the docker version setting up an environment variable called DEPENDENCIES.

NodeJS

npm install dependency1 dependency2 ...

Docker

docker run \
  -e HA_HOST=<your-host> \
  -e HA_TOKEN=<token> \
  -e MQTT_URI=<mqtt-uri> \
  -e DEPENDENCIES= dependency1 dependency2 ...
  -v <path/to/your/automations/folder>:/opt/app/src/automations \
  --restart=unless-stopped \
  danitetus/hass-sidecar:latest

__

Setup

The best way to setup is to create a .env file in the projects root folder. You have tu set these variables:

HA_HOST: http://your-host-or-ip:8123
HA_TOKEN: <token-provided-from-home-assistant>
MQTT_URI: mqtt://user:pass@server:port

Start

npm start

Creating automations

All automations have to be stored in ./src/automations (you can organize them in subfolders). They should extend Automation class.

Let's create an automation example. We are going to turn on and off a light when occupancy sensor changes:

/*
  ./src/automations/presenceLight.ts
*/

import { Automation } from '../interfaces/Automation.ts'

module.exports = class MyAutomation extends Automation {
  private lightEntity = '<entity_id>'
  private sensorEntity = '<entity_id>'

  constructor() {
    super('Title of my automation', 'Description') // Title and description are optional

    this.onStateChange(this.sensorEntity, (newState, oldState) => {
      if (newState.state === 'on') {
        this.callService('light', 'turn_on', this.lightEntity, {
          // Attributes are optional
          transition: 3
        })
      } else if (newState.state === 'off') {
        this.callService('light', 'turn_off', this.lightEntity, {
          // Attributes are optional
          transition: 3
        })
      }
    })
  }
}

Timeouts, intervals and runAt

To be able to create tasks in intervals or timeouts or simply execute a function at a certain time. You must use the methods of the Automation class dedicated to this. Do not use the NodeJS commands (setInterval, setTimeout, clearInterval, clearTimeout) because if your class has to be reloaded (due to a modification or because it has been removed), those callbacks will not be able to be removed, which will cause them to be executed anyway or the application fail.

Let's see an example of this:

/*
  ./src/automations/crazyLights.ts
*/

/**
 * Let's create an automation to do:
 *  - toggle a light every 10 seconds
 *  - say something in one speaker after 10 minutes
 *  - clear the interval when 60 seconds have passed
*/

import { Automation } from '../interfaces/Automation.ts'
import moment from 'moment'

module.exports = class CrazyLights extends Automation {

  // Define our private properties
  private lightEntity = '<entity_id>'
  private speakerEntity = '<entity_id>'
  private intervalId: NodeJS.Timeout

  /**
   * Instantiate
   */
  constructor () {
    // Good practice to define title and description (for the logs)
    super('Crazy lights', 'Lights going crazy')

    // Define toggle action on 10 seconds interval
    this.intervalId = this.setInterval(() => {
      this.callService('light', 'toggle', this.lightEntity)
    }, 10000)

    // Let's delete the interval after 60 seconds
    this.setTimeout(() => {
      this.clearTimeout(this.intervalId)
    }, 60000)

    // After 10 minutes, say something on the speaker
    this.runAt(moment().add(10, 'minutes').toDate(), () => {
      this.callService('tts', 'google_cloud_say', this.speakerEntity, {
        message: 'This light is crazy'
      })
    })
  }
}

Create your own libraries

You can create your own libraries to use in your automations. They have to be placed inside a "lib" folder. This is mandatory because these folders are ignored to load as automations.

Let's see an example:

/*
  ./src/automations/lib/sayHello.ts
*/

export sayHello = (name: string): string => {
  return `Hi ${name}!`
}
/*
  ./src/automations/sayHi.ts
*/

import { Automation } from '../interfaces/Automation.ts'
import { sayHello } from './lib/sayHello.ts'

module.exports = class SayHi extends Automation {
  constructor() {
    super('Say hello', 'Just for education')

    sayHello('Daniel')
  }
}

About logging

The app defines a custom logger that you can use in your automations. It allows you to trace the time of every log message and defines a color for each line based on the type: debug() = green info() = blue warning() = yellow error() = red log() = white

The typical console.log() statements are not recommended and will trigger lint errors.

Debug mode

To enable debug mode, you have to set the environment variable DEBUG to true.

hass-sidecar's People

Contributors

d4nicoder avatar abogaart avatar dependabot[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.