Skip to content
/ hass Public

An Emacs package for interacting with Home Assistant

License

Notifications You must be signed in to change notification settings

purplg/hass

Repository files navigation

hass

https://melpa.org/packages/hass-badge.svg https://stable.melpa.org/packages/hass-badge.svg

hass is an Emacs package that enables integration with Home Assistant. Call Home Assistant services, hook into Home Assistant events, and create convenient dashboards!

Contents

images/screenshot1.png

Installation

This package is available on MELPA.

use-package

(use-package hass
  :ensure t
  :init
  ;; -- Configuration goes here --
  )

straight.el

(straight-use-package 'hass)
;; -- Configuration goes here --

Doom Emacs

Place in your packages.el then run doom sync to pull the repository:

(package! hass)

Then load the package in your main config file.

(use-package! hass
  :init
  ;; -- Configuration goes here --
  )

Version 3 changes

Brand new dashboards!

Thanks to cprussin, the dashboards have been completely overhauled. They’re much more flexible by more cleanly utilizing the built-in widget framework. Additionally, you can have multiple dashboards configured.

hass-dash-layout is now hass-dash-layouts

hass-setup no longer required.

Calling hass-setup is no longer required. It has been renamed hass-ensure. It can still be useful if you want to ‘ensure’ an API connection has already been established and entity information is already up to date before you open a dashboard.

Removed deprecated :name widget property.

Removed polling-mode

Didn’t seem useful.

Configuration

Both hass-host and hass-apikey must be set to use this package. Set hass-host to the hostname or IP of Home Assistant instance. If you are not using SSL/TLS to connect to your Home Assistance instance, set hass-insecure to t. If you are using a port number other than the default 8123, specify the port number with hass-port.

(setq hass-host "homeassistant")
(setq hass-apikey "APIKEY-GOES-IN-HERE")
(setq hass-port 8123)

Alternatively, you can store a function inside hass-apikey. This will be executed on every query. In turn, this approach requires the token to be stored in your gpg store e.g. ~/.password-store/emacs-apikey.gpg

(setq hass-host "homeassistant")
(setq hass-apikey (lambda () (auth-source-pass-get 'secret "emacs-apikey")))

Once those variables are set, you can call (hass-ensure) to query the Home Assistance instance and populate available entities and services. Otherwise, this will be done when it is needed.

Getting an API Key

Ensure that your Home Assistant instance is configured to support API calls by following the instructions here.

Retrieve your API key a.k.a. Long-Lived Access Token by logging into your Home Assistant instance and going to your profile by selecting your username in the lower-left corner or going to this URL: http://HOME-ASSISTANT-URL:8123/profile. You can generate an API token at the very bottom of this page.

Dashboard layout

Full example

(setq hass-dash-layouts
      '((default . ; Key for dashboard. Shows up with completing-read when calling `hass-dash-open'.
                 ((hass-dash-group          ; Create a widget group.
                   :title "Home Assistant"  ; Give the group a title at the top.
                   :format "%t\n\n%v"       ; %t is where the title goes and %v is the widget it owns.
                   (hass-dash-group         ; Create a subgroup of widgets.
                    :title "Kitchen"
                    :title-face outline-2   ; Give it a unique face to make it stand out.
                    (hass-dash-toggle :entity-id "light.kitchen_lights")
                    (hass-dash-toggle :entity-id "light.master_bedroom_lights")
                    (hass-dash-toggle :entity-id "switch.entry_light"
                                      :label "Hallway" ; Override the widgets friendly name
                                      :confirm t)))    ; Require a y/n confirmation when toggling this entity.
                  (hass-dash-group :title "Group 2" :format "\n\n%t\n\n%v"
                                   (hass-dash-toggle :entity-id "light.master_bedroom_fan_light"))))

        (simple . ; Declaring a top-level group is optional and implied.
                ((hass-dash-toggle :entity-id "light.kitchen_lights")
                 (hass-dash-toggle :entity-id "switch.entry_lights")))))

Structure

To use the dashboard feature, hass-dash-layouts must be configure to tell hass what the layout should look like. The layout is constructed with three components: groups, widgets, and properties.

  • Each element in hass-dash-layouts is a dashboard.
  • A dashboard is a cons of its key/id and the widgets it contains.
  • A widget is an Emacs widget, probably one from this package.

Any widgets defined in hass-dash-layouts are automatically inserted into the hass-tracked-entities list in order to receive state updates.

Widgets

All widgets contain at least the following properties:

Widget PropertyDescription
:labelThe human readable label of the widget to be shown on the dashboard.
:serviceThe service to be called when the widget is selected.
:iconThe icon to be shown prefixed to the widget.
:confirmWhen t or a string, ask for confirmation before calling the service.

State

A ‘state’ widget is a read-only widget to simply display the state of some entity. I typically like to use this as the very first widget in a group to show the overall status of the group. For example, a vacuum:

(hass-dash-group :title "Vacuum"
                 (hass-dash-state :entity-id "vacuum.valetudo_vacuum" :format "%v\n")
                 ; Vacuum related widgets
                 ; ...
                 )

Button

A ‘button’ widget is a push-button widget to call a service.

(hass-dash-button :entity-id "vacuum.valetudo_vacuum"
                  :service "vacuum.start"
                  :format "%[%t: %v%]\n"
                  :label "Clean")

Toggle

A ‘toggle’ widget is similar to a button, except it’ll only show on or off. If the state is anything other than “on”, then it will show “off”.

(hass-dash-toggle :entity-id "light.kitchen")

Usage

To call a service on Home Assistant, use the hass-call-service function which has two required arguments: entity-id and service.

(hass-call-service "switch.bedroom_light" "switch.toggle")

If you call hass-call-service interactively, it will prompt you for an entity ID and then the respective service you want to call.

Dashboard

After configuring the hass-dash-layouts, use the function hass-dash-open to pop open a dashboard. This can be enhanced with standard buffer management configuration or packages like popper and/or shackle.

Payloads

For services that require additional data use the hass-call-service-with-payload function. The second argument, payload, requires an JSON encoded string.

This example publishes to an MQTT topic:

(hass-call-service-with-payload
 "mqtt.publish"
 (json-encode '(("payload" . "PERFORM")
                ("topic" . "valetudo/vacuum/LocateCapability/locate/set"))))

You could pass a JSON string directly, but that would require escaping every quote which can be cumbersome. Here’s what the encoded list above looks like in JSON:

{
  "payload": "PERFORM",
  "topic": "valetudo/vacuum/LocateCapability/locate/set"
}

Hooks

The most useful hook is a function list named hass-entity-state-changed-functions. Functions in this list are passed a single argument entity-id which is the entity id of the entity whose state has changed since it was last updated. Using this function hook along side tracking entities enables Emacs to react to changes to Home Assistant entities.

This example will display the state of an entity when it changes:

(add-hook 'hass-entity-state-changed-functions
  (lambda (entity-id)
    (message "The entity %s state has changed to %s." entity-id (hass-state-of entity-id))))

The other two hooks available are hass-entity-updated-hook and hass-service-called-hook. hass-entity-updated-hook is called when the state of an entity is updated, regardless of if it changed or not. hass-service-called-hook is called when a service is called.

(add-hook 'hass-service-called-hook (lambda () (message "A service was called.")))
(add-hook 'hass-entity-updated-hook (lambda () (message "An entitys' state was updated.")))

License

MIT