mirror of
https://github.com/correl/correl.github.io.git
synced 2024-12-27 11:07:35 +00:00
New blog post on Home Assistant
This commit is contained in:
parent
c66f121f8c
commit
46933271bf
6 changed files with 375 additions and 1 deletions
376
blog.org
376
blog.org
|
@ -1,7 +1,7 @@
|
|||
#+STARTUP: indent inlineimages hideblocks
|
||||
#+HUGO_BASE_DIR: .
|
||||
#+HUGO_SECTION: blog
|
||||
#+OPTIONS: toc:nil num:nil todo:nil
|
||||
#+OPTIONS: toc:nil num:nil todo:nil d:(not "HIDDEN")
|
||||
#+PROPERTY: header-args :cache yes :eval never-export :output-dir static/ox-hugo/
|
||||
#+COLUMNS: %TODO %50ITEM %CLOSED %EXPORT_FILE_NAME %CATEGORY %TAGS
|
||||
#+LINK: relref file:{{< relref "%s.md" >}}
|
||||
|
@ -2718,3 +2718,377 @@ trigger each other.
|
|||
If I get around to building my rolling sunrise, I'll be sure to get a
|
||||
post up on it :)
|
||||
|
||||
* DONE Automating My Apartment With Home Assistant :home_automation:
|
||||
CLOSED: [2019-06-27 Thu 18:13]
|
||||
:PROPERTIES:
|
||||
:EXPORT_FILE_NAME: automating-my-apartment-with-home-assistant
|
||||
:END:
|
||||
|
||||
A while ago, I [[relref:hue-wake-up][posted about]] my experiments with the Phillips Hue API
|
||||
to create an automated morning sunrise effect. The end result was
|
||||
nice, but all that mucking about with their HTTP APIs was a hassle any
|
||||
time I wanted to tweak something. I wanted to define what I wanted in
|
||||
a more declarative style, and have all the API calls managed behind
|
||||
the scenes. [[https://www.home-assistant.io/][Home Assistant]] allowed me to do exactly that, and more.
|
||||
|
||||
While the Home Assistant docs are geared heavily towards setting up a
|
||||
raspberry pi appliance to run everything 24/7, I don't own one, and I
|
||||
already have a server going. I opted instead to get the home assistant
|
||||
server running using [[https://www.home-assistant.io/docs/installation/docker/][Docker]], and setting up a git repository to hold
|
||||
my configuration.
|
||||
|
||||
** A Brand New Day
|
||||
Setting up my sunrise was actually /really/ easy. I already had the
|
||||
scenes I wanted from my [[relref:hue-wake-up][previous attempt]], so it was just a matter of
|
||||
codifying them in the YAML config. I split them into four scenes - a
|
||||
start (dawn) and end (daylight) pair for the standing lamp at the wall
|
||||
beyond the foot of the bed, and a pair for the two nightstand lights.
|
||||
The end scenes include the transition time to fade in (30 minutes).
|
||||
|
||||
#+begin_src yaml
|
||||
scene:
|
||||
- name: Dawn Sun
|
||||
entities:
|
||||
light.standing_lamp:
|
||||
state: on
|
||||
brightness: 1
|
||||
xy_color: [0.6042, 0.3739]
|
||||
- name: Dawn Daylight
|
||||
entities:
|
||||
light.correls_nightstand:
|
||||
state: on
|
||||
brightness: 1
|
||||
xy_color: [0.2376, 0.1186]
|
||||
light.stephanies_nightstand:
|
||||
state: on
|
||||
brightness: 1
|
||||
xy_color: [0.2376, 0.1186]
|
||||
- name: Sunrise Sun
|
||||
entities:
|
||||
light.standing_lamp:
|
||||
state: on
|
||||
transition: 1800
|
||||
brightness: 254
|
||||
xy_color: [0.3769, 0.3639]
|
||||
- name: Sunrise Daylight
|
||||
entities:
|
||||
light.correls_nightstand:
|
||||
state: on
|
||||
transition: 1800
|
||||
brightness: 203
|
||||
xy_color: [0.2698, 0.295]
|
||||
light.stephanies_nightstand:
|
||||
state: on
|
||||
transition: 1800
|
||||
brightness: 203
|
||||
xy_color: [0.2698, 0.295]
|
||||
#+end_src
|
||||
|
||||
Breaking them apart this way means I can trigger the "sun" first for a
|
||||
splash of orange, then start up the nightstand "daylight" lights a
|
||||
little bit later! This worked out well, too, since even at the lowest
|
||||
brightness, having them turn on right at the start when the room is
|
||||
totally dark had a tendency to jolt me awake. Staggering them produces
|
||||
a much gentler effect. Scripting all of this took very little work...
|
||||
|
||||
#+begin_src yaml
|
||||
script:
|
||||
sunrise:
|
||||
alias: Sunrise
|
||||
sequence:
|
||||
- service: scene.turn_on
|
||||
data:
|
||||
entity_id: scene.dawn_sun
|
||||
- service: scene.turn_on
|
||||
data:
|
||||
entity_id: scene.sunrise_sun
|
||||
- delay:
|
||||
seconds: 180
|
||||
- service: scene.turn_on
|
||||
data:
|
||||
entity_id: scene.dawn_daylight
|
||||
- service: scene.turn_on
|
||||
data:
|
||||
entity_id: scene.sunrise_daylight
|
||||
#+end_src
|
||||
|
||||
... and the end result really is quite pleasant:
|
||||
|
||||
#+begin_src ditaa :file ha-lights-1.png :exports none
|
||||
+----+
|
||||
|cA20|
|
||||
| |
|
||||
|{o} |
|
||||
+----+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+----+ Z +----+
|
||||
|cBLK| z |cBLK|
|
||||
| | z | |
|
||||
|{o} | |{o} |
|
||||
+----+ +----+
|
||||
|
||||
6꞉30 AM
|
||||
#+end_src
|
||||
|
||||
#+RESULTS[bb260c3d0d038bb1fdcd6cba2076efeff57bad80]:
|
||||
[[file:static/ox-hugo/ha-lights-1.png]]
|
||||
|
||||
#+begin_src ditaa :file ha-lights-2.png :exports none
|
||||
+----+
|
||||
|cB50|
|
||||
| |
|
||||
|{o} |
|
||||
+----+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+----+ +----+
|
||||
|c327| z |c327|
|
||||
| | z | |
|
||||
|{o} | |{o} |
|
||||
+----+ +----+
|
||||
|
||||
6꞉33 AM
|
||||
#+end_src
|
||||
|
||||
#+RESULTS[07189ab694076463b9a88997b2f8be6427ea6950]:
|
||||
[[file:static/ox-hugo/ha-lights-2.png]]
|
||||
|
||||
#+begin_src ditaa :file ha-lights-3.png :exports none
|
||||
+----+
|
||||
|cFFD|
|
||||
| |
|
||||
|{o} |
|
||||
+----+
|
||||
|
||||
|
||||
\o/
|
||||
|
|
||||
|
|
||||
/ \
|
||||
+----+ +----+
|
||||
|cDDF| |cDDF|
|
||||
| | | |
|
||||
|{o} | |{o} |
|
||||
+----+ +----+
|
||||
|
||||
7꞉00 AM
|
||||
#+end_src
|
||||
|
||||
#+RESULTS[b22835dedc7d706f3f8ff6826040349decbb5d1a]:
|
||||
[[file:static/ox-hugo/ha-lights-3.png]]
|
||||
|
||||
#+begin_center
|
||||
[[file:static/ox-hugo/ha-lights-1.png]]
|
||||
[[file:static/ox-hugo/ha-lights-2.png]]
|
||||
[[file:static/ox-hugo/ha-lights-3.png]]
|
||||
#+end_center
|
||||
|
||||
That just leaves the automation, which fires a half an hour before the
|
||||
/actual/ sunrise, so long as the lights aren't already on and somebody
|
||||
is home (using a binary sensor I defined elsewhere based on phones
|
||||
detected in the house plus an override toggle).
|
||||
|
||||
#+begin_src yaml
|
||||
automation:
|
||||
- alias: Sunrise
|
||||
action:
|
||||
- service: script.sunrise
|
||||
data: {}
|
||||
trigger:
|
||||
- platform: sun
|
||||
event: sunrise
|
||||
offset: '-00:30:00'
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: binary_sensor.occupied
|
||||
state: 'on'
|
||||
- condition: state
|
||||
entity_id: group.bedroom_lights
|
||||
state: 'off'
|
||||
#+end_src
|
||||
|
||||
I later extended the automation with some configuration inputs, which
|
||||
tie into some new triggers and conditions. I added a "latest start
|
||||
time" to make sure it always gets me up in time for me to get ready
|
||||
for work, and an option to disable the wake-up on weekends.
|
||||
|
||||
#+begin_src yaml
|
||||
input_select:
|
||||
sunrise_days:
|
||||
name: Days to wake up
|
||||
options:
|
||||
- Every Day
|
||||
- Weekdays
|
||||
initial: Every Day
|
||||
icon: mdi:weather-sunset
|
||||
input_datetime:
|
||||
sunrise_time:
|
||||
name: Latest start time
|
||||
has_date: false
|
||||
has_time: true
|
||||
initial: '06:30'
|
||||
automation:
|
||||
- alias: Sunrise
|
||||
action:
|
||||
- service: script.sunrise
|
||||
data: {}
|
||||
trigger:
|
||||
- platform: sun
|
||||
event: sunrise
|
||||
offset: '-00:30:00'
|
||||
- platform: template
|
||||
value_template: >-
|
||||
{{ states('sensor.time') == (
|
||||
states.input_datetime.sunrise_time.attributes.timestamp
|
||||
| int | timestamp_custom('%H:%M', False)
|
||||
)
|
||||
}}
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: binary_sensor.occupied
|
||||
state: 'on'
|
||||
- condition: state
|
||||
entity_id: group.bedroom_lights
|
||||
state: 'off'
|
||||
- condition: or
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.sunrise_days
|
||||
state: Every Day
|
||||
- condition: and
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: input_select.sunrise_days
|
||||
state: Weekdays
|
||||
- condition: time
|
||||
weekday:
|
||||
- mon
|
||||
- tue
|
||||
- wed
|
||||
- thu
|
||||
- fri
|
||||
#+end_src
|
||||
|
||||
Sprinkle in some groups, and I've got a nice panel in my Home
|
||||
Assistant UI to manage everything:
|
||||
|
||||
#+CAPTION: The completed sunrise panel
|
||||
#+ATTR_ORG: :width 800
|
||||
[[file:static/images/ha-sunrise-ui.png]]
|
||||
|
||||
** Keep It Down!
|
||||
|
||||
Determined to find more things to automate, I realized that since I
|
||||
have my TV audio going through a Sonos sound bar, I could very easily
|
||||
automate the rather annoying ritual of leaping for the app on my phone
|
||||
to turn on night mode when a movie I'm watching is getting explodey
|
||||
and I realize it's a bit late in the evening to be shaking my
|
||||
neighbor's walls.
|
||||
|
||||
#+begin_src yaml
|
||||
automation:
|
||||
- alias: Toggle Sonos night mode
|
||||
action:
|
||||
- service: media_player.sonos_set_option
|
||||
entity_id: media_player.den
|
||||
data_template:
|
||||
night_sound: >-
|
||||
{{ now().hour >= 22 }}
|
||||
trigger:
|
||||
- platform: time
|
||||
at: '22:30:00'
|
||||
- platform: time
|
||||
at: '08:00:00'
|
||||
#+end_src
|
||||
|
||||
Boom. Happier neighbors, and I can fall asleep in front of movies
|
||||
without worry!
|
||||
|
||||
Just because I could, I also added some configurability to this
|
||||
automation as well. The logic got a bit tricky, since I wanted to
|
||||
configure a window that crosses a 24-hour boundary. I also added a
|
||||
binary sensor so I could see when night mode was enabled from Home
|
||||
Assistant.
|
||||
|
||||
#+begin_src yaml
|
||||
automation:
|
||||
- alias: Toggle Sonos night mode
|
||||
action:
|
||||
- service: media_player.sonos_set_option
|
||||
entity_id: media_player.den
|
||||
data_template:
|
||||
night_sound: >-
|
||||
{% set start = states.input_datetime.sonos_nightmode_start.attributes %}
|
||||
{% set end = states.input_datetime.sonos_nightmode_end.attributes %}
|
||||
{% set now_ = (now().hour, now().minute, now().second) %}
|
||||
{% set start_ = (start.hour, start.minute, start.second) %}
|
||||
{% set end_ = (end.hour, end.minute, end.second) %}
|
||||
{% if start_ > end_ -%}
|
||||
{{ now_ >= start_ or now_ < end_ }}
|
||||
{%- else -%}
|
||||
{{ now_ >= start_ and now_ < end_ }}
|
||||
{%- endif -%}
|
||||
trigger:
|
||||
- platform: template
|
||||
value_template: "{{ states('sensor.time') == (states.input_datetime.sonos_nightmode_start.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
|
||||
- platform: template
|
||||
value_template: "{{ states('sensor.time') == (states.input_datetime.sonos_nightmode_end.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
|
||||
sensor:
|
||||
- platform: time_date
|
||||
display_options:
|
||||
- time
|
||||
input_datetime:
|
||||
sonos_nightmode_start:
|
||||
name: Start Night Mode
|
||||
has_date: false
|
||||
has_time: true
|
||||
initial: '22:30'
|
||||
sonos_nightmode_end:
|
||||
name: End Night Mode
|
||||
has_date: false
|
||||
has_time: true
|
||||
initial: '08:00'
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
sensors:
|
||||
den_night_mode:
|
||||
friendly_name: Sonos Den Night Mode
|
||||
value_template: >-
|
||||
{{ state_attr('media_player.den', 'night_sound') }}
|
||||
#+end_src
|
||||
|
||||
And, voilà, a dashboard for my speakers, which I pretty much never
|
||||
need to look at anymore!
|
||||
|
||||
[[file:static/images/ha-sonos-ui.png]]
|
||||
|
||||
** But Wait, There's More!
|
||||
|
||||
It's a too much to cover in a single blog post, but there's plenty
|
||||
more going on in my config. Over time, I've tweaked and added to my
|
||||
device tracking to make sure Home Assistant knows when someone's home.
|
||||
I set up some text-to-speech to announce the weather in the morning,
|
||||
and welcome the first person to get home. I even re-purposed an old
|
||||
phone as a webcam so I can check on the cat while I'm out. My config
|
||||
is on my personal gitlab server, feel free to check it out and see if
|
||||
there's anything there you can use or learn from:
|
||||
http://git.phoenixinquis.net/correlr/home-assistant
|
||||
|
||||
* TODO Types in Python :programming:python:
|
||||
:PROPERTIES:
|
||||
:EXPORT_FILE_NAME: types-in-python
|
||||
:END:
|
||||
|
||||
** TODO Why Use Types?
|
||||
** TODO Success Typing
|
||||
** TODO Running Mypy
|
||||
** TODO Specifying Types
|
||||
|
|
BIN
static/images/ha-sonos-ui.png
Normal file
BIN
static/images/ha-sonos-ui.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
BIN
static/images/ha-sunrise-ui.png
Normal file
BIN
static/images/ha-sunrise-ui.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
BIN
static/ox-hugo/ha-lights-1.svg
Normal file
BIN
static/ox-hugo/ha-lights-1.svg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
BIN
static/ox-hugo/ha-lights-2.svg
Normal file
BIN
static/ox-hugo/ha-lights-2.svg
Normal file
Binary file not shown.
After Width: | Height: | Size: 6 KiB |
BIN
static/ox-hugo/ha-lights-3.svg
Normal file
BIN
static/ox-hugo/ha-lights-3.svg
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
Loading…
Reference in a new issue