diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..97fedd9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,8 @@ +As a **actor**, I want **something** so that I can **goal**. + +### Acceptance criteria +1. It's done when . +1. It's done when . + +### Additional details +- diff --git a/.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md b/.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md new file mode 100644 index 0000000..39ccd7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG_TEMPLATE.md @@ -0,0 +1,11 @@ +### Description + + +### Scenario +1. +1. + +### Expected result + + +### Actual result diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..4484178 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ +### Short description of what this resolves + + +### Changes proposed in this pull request + + +### Fixes issue number diff --git a/.gitignore b/.gitignore index ac42539..bc6dd84 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ OZW_Log.txt plex.conf secrets.yaml +!.github !.gitignore !.gitkeep !/.travis.yml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d064ac7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "custom_components/display"] + path = custom_components/display + url = https://github.com/daemondazz/homeassistant-displays.git diff --git a/.travis.yml b/.travis.yml index d3aeada..fc86e69 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,12 @@ # language: python python: - - "3.5" + - "3.6" before_install: - cp secrets-dummy.yaml secrets.yaml + - touch home-assistant_v2.db + - touch home-assistant.log install: - pip3 install homeassistant script: - - hass -c . --script check_config + - hass --script check_config -c . -f diff --git a/README.md b/README.md index 0fd7775..354f1ec 100644 --- a/README.md +++ b/README.md @@ -2,218 +2,363 @@ [![Build Status][img-travis-ci]][link-travis-ci] [![GitHub Release][img-github-release]][link-repo] -[![Repo Size][img-repo-size]][link-repo] -[![Code Size][img-code-size]][link-repo] [![Hass.io][img-hassio]][link-hassio] +[![Home Assistant version][img-ha-version]][link-ha-version] [![License][img-license]][link-license] + + Configuration for [Home Assistant](https://home-assistant.io/) running [Hass.io](https://home-assistant.io/hassio/) on a Raspberry Pi for a one bedroom apartment, offering convenience automations over lights and climate while providing multiple intuitive user controls. +
+
+
+ Dashboard animation +
+
+

Wall-mounted interface using /appdaemon/dashboards/.

+
+
+
+ +
+
+
+ Security group (Dark theme) + Weather group + Climate Control group + Battery Levels group (Dark theme) + Atmospheric Safety group + Actions group + Ceiling group + Public Transit group +
+
+

Sensor /groups/.

+
+
+
+ + ## Contents + 1. **[TL;DR](#tldr)** -1. **[Overview](#overview)** - [User stories](#user-stories) | [Goals](#goals) -1. **[Key features](#Goals)** - [Climate control](#climate-control) | [Weather report](#weather-report) | [Lighting control](#lighting-control) | [Presence](#presence) | [Scenes and actions](#scenes-and-actions) | [General information](#general-information) | [Human interfaces](#human-interfaces) -1. **[Task list](#task-list)** - [Work in progress](#work-in-progress) | [Backlog](#backlog) | [Wishlist](wWishlist) -1. **[Setup](#setup)** - [System and interfaces](#system-and-interfaces) | [Devices and sensors](#devices-and-sensors) | [Software](#software) | [Hass.io add-ons](#hassio-add-ons) | [Community components and widgets](#community-components-and-widgets) +1. **[Overview](#overview)** + [Goals](#goals) | [Agile development](#agile-development) +1. **[Key features](#Goals)** + [Climate control](#climate-control) | [Weather report](#weather-report) | [Lighting control](#lighting-control) | [Presence and basic security](#presence-and-basic-security) | [Modes and scenes](#modes-and-scenes) | [General information](#general-information) | [Additional human interfaces](#additional-human-interfaces) +1. **[Setup](#setup)** + [Diagram](#diagram) | [Supporting hardware choices](#supporting-hardware-choices) | + [Configuration](#configuration) | [System and interfaces](#system-and-interfaces) | [Physical devices](#physical-devices) | [Software](#software) 1. **[Thanks](#thanks)** + ## TL;DR This is a fully documented working configuration for Home Assistant, with screenshots, hints and comments. [Browse the code](#) to have a look! + ## Overview -### User stories +### Goals +- **Inconspicuous**: I like tech alright, but like any good butlers it should stay out of sight yet stay summonable. Think Fiji villa, not server room. +- **Modular**: Both code and devices should be easily replaceable. +- **Internet independent**: As much local processing as possible for the essential features. +- **Accessible through multiple ways:** Computers, tablet (kiosk), voice, smart phones, wireless buttons. +- **Intuitive user interfaces:** One look at a group of sensors/switches should be sufficient for anyone to understand the current states and how to operate an interface. +- **Redundant controls:** Multiple interfaces should be able to control devices without interference. State changes from manual interventions or dedicated manufacturer apps should be tracked whenever possible. +- **No information overload:** Provide just enough insights to get an idea of what's going on. And no need for data that's best consumed on more interactive devices (like stock prices, Steam community status...) +- **Not everything should be networked:** Bathroom fan, pantry and laundry room lights have their independent motion sensors and that's a good thing. Same independence goes for the smoke detector: I sure don't want to require extensive skin grafts because I forgot an extra space in a YAML file. _Yikes!_ +- **No Alexa/Cortana/Google Voice:** I don't want to have advertising agencies, online stores, or other AI-feeding Big Brother tech-monsters listening in to everything we say _and do_ just for the dubious convenience of switching lights on by voice command. There are offline solutions that are privacy-counscious. + +
+
+
+ Wiretap meme +
+
+

No thanks!

+
+
+
+ + +### Agile development + +This configuration is built with an [Agile](http://agilemanifesto.org/)-like methodology, lead by following main user stories: + - **As a resident** I want a reliable home automation platform to handle lights and climate that can easily be controlled and overridden in many intuitive ways. - **As an apartment dweller** I want to have a discrete, non-permanent installation that takes as little space as possible. - **As a developer** I want to use an open-source platform that is feature-rich, accessible, flexible and actively maintained. - **As a consumer** I want to pick and choose which devices I wish to acquire without necessarily being locked into a closed ecosystem. - **As a couple** we want to be able to operate lights and climate-control appliances as well as get quick overview of weather forecasts and public transit schedules through simple to use interfaces. -### Goals -- **Inconspicuous**: I like tech alright, but like good butlers it should stay out of sight but summonable when desired. Think Fiji villa, not server room. -- **Modular**: Both code and devices should be easily replaceable. -- **Internet independent**: As much local processing as possible for the essential features. -- **Accessible through multiple ways:** Computers, tablet (kiosk), voice, smart phones, wireless buttons. -- **Intuitive user interfaces:** One look as a group of sensors/switches should be sufficient for anyone to understand the current states and how to operate an interface. -- **Redundant controls:** Multiple interfaces should be able to control devices without interference, and state changes from manual interventions or dedicated manufacturer apps should be tracked when possible. -- **No information overload:** Provide just enough insights to get an ideas of what's going on. And no need for data that's best consumed on more interactive devices (like stock prices, Steam community status...) -- **Not everything should be networked:** Bathroom fan, pantry and laundry room lights have their independent motion sensors and that's a good thing. Same independence goes for the smoke detector: I sure don't want to require extensive skin grafts because I forgot an extra space in a YAML file. _Eek!_ -- **No Alexa/Cortana/Google Voice:** I don't want to have advertising agencies, online stores, or other AI-feeding Big Brother tech-monsters listening in to everything we say just for the dubious convenience of turning on a light using my voice. +Tasks are defined in the [issue queue][link-issues] and the development progress is managed using a [lightweight Kanban board][link-board]. + +
+
+
+ Agile. You keep using that word. I do not think it means what you think it means. +
+
+

Well, without the sprints. And a team. And the retrospectives. And the...

+
+
+
## Key features ### Climate control -- **Temperature monitoring**, averaged to compensate for sensor calibration inaccuracies, then rounded. +- **Temperature monitoring**, averaged and rounded to compensate for sensor calibration issues. - **Humidity monitoring**, also averaged and rounded. - **Toggle dehumidifier when needed**, based on humidity averaged from multiple sensors, and only during the afternoon so not to bother anyone. - **Turn dehumidifier off when windows/doors are opened**, instantly for windows and after a few minutes for doors. -- **Low/High humidity status and alerts**, in case something is wrong with the dehumidifier or the (eventual) humidifier. +- **Low/High humidity status and alerts**, in case something is wrong with the dehumidifier or the humidifier. - **Mold conditions status and alert**, in case dehumidifier is full/overwhelmed or someone transformed the place into a steam room. +
+
+
+ Climate Control group + Humidity notification +
+
+

Climate control.

+
+
+
+ + ### Weather report -- **Easy to read status and forecasts** using Dark Sky data and only showcasing parameters that actually matter, shown in obvious ways. -- **Outdoor quality monitoring** with numeric levels and human-friendly categorization for ozone, carbon monoxide, nitrogen dioxide, 2.5μm particulate matter and UV light, averaged from multiple surrounding public local stations. +- **Easy to read status and forecasts** using [Dark Sky](https://darksky.net/) data and only showcasing parameters that actually matter, shown in obvious ways. +- **Outdoor quality monitoring** with numeric levels and human-friendly categorization for ozone, carbon monoxide, nitrogen dioxide, sulphur dioxide, 2.5μm particulate matter and UV light, averaged from multiple surrounding public local stations. - **Weather radar and satellite maps** for [local rain and snow](https://weather.gc.ca/radar/index_e.html) from Environment Canada and [regional air masses](http://www.nhc.noaa.gov/satellite.php) from the U.S. National Oceanic and Atmospheric Administration. -- See [`/groups`](groups) and [`/appdaemon/dashboards`](appdaemon/dashboards). +- See [`/groups/`](groups) and [`/appdaemon/dashboards/`](appdaemon/dashboards). + +
+
+
+ Today's Weather group + Weekly Forecast group +
+
+

Today's weather and weekly forecast.

+
+
+
+ ### Lighting control -- **Control for all pluggable lights**, smart ones at [`/lights`](lights) and dumb ones using [`/switches`](switches). +- **Control for all pluggable lights**, smart ones at [`/lights/`](lights) and basic ones using [`/switches/`](switches). - **Nanoleaf Aurora control**: + Manual theme selection. + Automatically rotate through device-based themes based on time of day (unless manually selected above). - **LIFX Z bed underglow lights and ceiling wash lights control**: + Manual theme selection. + Automatically rotate through cloud-based themes based on time of day (unless manually selected above). -- **Automatically correlated color temperature (CCT)**, for [f.lux](https://justgetflux.com/)-like white temperature shift to gradually remove blue light based on a custom color and brightness curve and preset active hours, not simply based on the sun otherwise Canadian winters would be pretty yellow. -- **Presence-based nightlights**, where strategic lights fade in, dimmed very low, when walking around at night, say when someone wakes up to go the bathroom ...again. -- See [`/automations`](automations). - -### Presence -- **Opened door binary sensor**, to know if someone left a door open. -- **Opened door indicator in shower** where the shower stall's light changes color briefly and subtly when the front door opens/closes, to indicate a showering partner that their better half has left or just came in. +- **Automatically correlated color temperature (CCT)**, for [f.lux](https://justgetflux.com/)-like white temperature shift to gradually remove blue light based on a custom color and brightness curve, not simply based on the sun ...otherwise Canadian winters would be quite yellow! +- **Motion-based nightlights**, where strategic lights fade in, dimmed very low, when movement is detected at night, say when someone wakes up to go the bathroom ...again. +- See [`/lights/`](lights) and [`/automations/`](automations). + +
+
+
+ Lounge group + Bedroom group +
+
+

Lighting controls.

+
+
+
+ + +### Presence and basic security +- **Cellphone device sensing**, to check who is currently home or away. +- **Tamper monitoring**, in case a perimeter device has been played with. +- **Opened door alert**, to know if someone left an exteral door open. +- **Opened door indicators** where a chime is played and a few lights change color briefly and subtly when the front door opens/closes, say to indicate an oblivious showering partner that their better half has left or just came in. + +
+
+
+ Presence group + Security Status group +
+
+

Presence and basic security.

+
+
+
+ + +### Modes and scenes +- **Mode based** where unless a blocking mode is set, devices will turn on. Think of a river or a horse: tame it to keep it under control, but release the restraints and they will do their thing: 🐎 + + **Quiet mode** where noise makers know to stop or not to start. + + **Nap time mode** that fades out lights in and near the bedroom and enables quiet mode. + + **Night mode** fades out all lights outside of bedroom, enabling quiet mode too. + + **Low-power mode** where each room knows which device should be on or off to achieve a more economical and calm state. +- **Smart rooms** that know which devices should be on or off based on the modes above. No need for heavy centralized control, let local managers handle their teams! +- **Good morning action** that releases all blocking modes, allowing all lights to turn on gradually, and noise-making devices are allowed to run if needed. +- **Smart global scenes** based on [`/scripts/`](scripts)` instead of scenes, to allow for sequences and conditions: + + **Movie scene** turns on ambiance lighting and dims smart lights when playing a movie, then returns to standard automations when pausing/stopping. + + **Daylight, Gaming and Romantic global scenes** fades in and out different lights, sets effects and changes light colors to set a perfect mood. + +
+
+
+ Actions group +
+
+

Modes and scenes.

+
+
+
-### Scenes and actions -- **Good morning action** where all lights turn on gradually, and noise-making devices are allowed to run if needed. -- **Nap time action** that fades out lights in and near bedroom, turns off noise makers. -- **Good night action** fades out all lights outside of bedroom, turns off noise makers too. -- **Movie scene** turns on ambiance lighting and dims smart lights when playing a movie, then returns to standard automations when pausing/stopping. ### General information -- **[Local bus schedules](https://home-assistant.io/components/sensor.gtfs/)** with the next 3 departures. See [`/gtfs`](gtfs) for optimization hints. +- **[Local bus schedules](https://home-assistant.io/components/sensor.gtfs/)** with the next 3 departures. See [`/gtfs/`](gtfs) for optimization hints. - **[Doomsday Clock](https://github.com/renemarc/home-assistant-custom-components)** in case egocentric psychopaths keep on playing Russian roulette with humanity's future. - **Network status monitoring** for latency, upspeed, downspeed. -- **Home Assistant status monitoring** for geek cred with average load, RAM use, disk use, uptime, and update availability. - -### Human interfaces -- **Flic button on nightstand** for trigerring _good morning_ and _nap time_ actions, as well as bedroom light control, depending on current state and click sequence. -- **[Homebridge](https://github.com/nfarina/homebridge)** for using some key sensors and devices with iPhones (only if using the same VLAN though). -- **[Home Assistant Companion](https://itunes.apple.com/us/app/home-assistant-companion/id1099568401?mt=8) iPhone app** for full UI access in the palm of my hand. _Muahahaha!__ -- **[HADashboard](https://home-assistant.io/docs/ecosystem/hadashboard/)** for wall-mounted tablet, featuring indoor sensors reports, transit schedules, weather forecast and radar/sattelite maps, wrapped in an obvious navigation scheme for much UX goodness. Have a look at [`/appdeamon/dashboards`](appdeamon/dashboards), you'll like! - - -### Task list - -#### Work in progress -- Device: Kitchen under-cabinet CCT lighting -- Device: Flic button (kitchen) -- Contribute back: Full documentation - -#### Backlog -- Component: Fix unlimited bandwidth consumption bug -- Scene: Romantic -- Scene: Gaming/Party -- Automation: Away mode -- Interface: Voice command (snips.ai) -- Presence detection: Cellphones -- Presence detection: Router -- Contribute back: GTFS sensor optimization and documentation -- Contribute back: HADashboard widget optimizations - -#### Wishlist -- Dashboard: Context-aware link widgets -- Automation: Welcome home theme song front door trigger -- Automation: Door/Window sensor temper alert -- Component: Airthings BLE custom component -- Component: Monitor indoor air quality -- Component: UPS monitoring -- Component: Read rooftop weather station (Fine Offset WH1080) -- Device: Use USB gigabit connection to test for above 80MB/s downspeeds -- Device: Replace Wifi plug-in outlets with Z-Wave for stability -- Device: Increase nightlight movement detection coverage -- Device: Window binary sensors/state overview -- Device: Indoor air quality sensing and report -- Device: Exterior light -- Device: Monitor humidity in humidor -- Device: Light patterns in windowed cabinets using H801 devices -- Device: Motion nightlight in bathroom under mirror -- Device: Fade in/out fairy lights and nightstand lamp using ESP8266 devices -- Device: Timer-based, fade in/out, twinkling Christmas tree using Arduino +- **Home Assistant status monitoring** for geek cred with average load, RAM use, disk use, uptime, and update availability. 🤓 + +
+
+
+ System group + Public Transit group +
+
+

General information.

+
+
+
+ + +### Additional human interfaces +- **Flic buttons** on nightstand and in the kitchen for triggering modes and controlling localized lights, depending on current states and click types. +- **Aeotec Minimote** to quickly control global scenes and modes. +- **[Homebridge](https://github.com/nfarina/homebridge)** for using some key sensors and devices with iPhones. +- **[Home Assistant Companion](https://itunes.apple.com/us/app/home-assistant-companion/id1099568401?mt=8) iPhone app** for full UI access in the palm of my hand. _Muahahaha!_ +- **[HADashboard](https://home-assistant.io/docs/ecosystem/hadashboard/)** for wall-mounted tablet, featuring indoor sensors reports, transit schedules, weather forecast and radar/sattelite maps, wrapped in an obvious navigation scheme for much UX goodness. Have a look at [`/appdaemon/dashboards/`](appdaemon/dashboards), you'll like! 😍 ## Setup +### Diagram +
+
+
+ Technology diagram +
+
+

Technology Diagram (PNG, SVG). Made with Draw.io (XML source file).

+
+
+
+ + ### Supporting hardware choices - **Ubiquiti router and access point** because forking over some dough for reliable, rock-solid prosumer networking gear makes everything run smoothly. And because hearing one less complaint (dropped wifi signal) from the girlfriend is priceless. \*sigh\* - **Uninterruptible power supply** to ride over transient power failures. - **Z-Wave** for reliability and guaranteed interoperability between vendors (unlike Zigbee...) - **Wifi** for its cheapness, omnipresence and non requirement of vendor-specific hubs. + ### Configuration -- **Dedicated, firewalled VLAN** (Virtual LAN) to segregate all IoT devices from other equipment ...because I cannot trust that my vacuum cleaner won't go on a killing spree. Remember [Runaway with Tom Selleck](http://www.imdb.com/title/tt0088024/)? Eek! +- **Dedicated, firewalled VLAN** (Virtual LAN) to segregate all IoT devices from other equipment ...because I cannot trust that my vacuum cleaner won't go on a killing spree. Ever seen [_Runaway (1984)_](https://www.youtube.com/watch?v=zCZY9Z6WvSY) with Tom Selleck? Eek! 😱 - **Local static IPs** for all devices to minimize random drops. -- **Local development** on a local virtual machine using Docker, then pushed by GIT to a Raspberry Pi. -- **Shareable code** with all identifiers kept in a non-committed, secrets file. +- **Local development** on a local virtual machine using Docker, then pulled with GIT on a Raspberry Pi. +- **Shareable code** with all identifiers kept in a non-committed, _secrets_ file. +- **Loads of documentation**, for my later self and to help out others. + ### System and interfaces - **[Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)** running Hass.io. - **[Aeotec Z-Stick Gen5](https://aeotec.com/z-wave-usb-stick)** Z-Wave USB dongle. - **[NooElec NESDR SMArt](http://www.nooelec.com/store/nesdr-smart.html)** RTL-SDR (software-defined radio) USB dongle for reading AcuRite sensors. -- **[Plugable USB Bluetooth Adapter](https://plugable.com/products/usb-bt4le/)** for Bluetooth Low Energy connections. - **[Milight iBox2 Wifi Bridge](https://www.futlight.com/productdetails.aspx?id=239&typeid=125)** for kitchen RF LED strip controllers, using [LimitlessLED](https://home-assistant.io/components/light.limitlessled/) integration. -- **[Acer Iconia One 10" tablet](https://www.acer.com/ac/en/CA/content/series/iconiaone10)** (1280x800 IPS screen) wallmounted as a kiosk. See [`/appdaemon/dashboards/`](appdaemon/dashboards) -### Devices and sensors + +### Physical devices + +#### Lights - **[Nanoleaf Aurora](https://nanoleaf.me)** light panels kit. Pretty! - **[LIFX+](https://www.lifx.com/products/lifx-plus)** A19 RGB light bulb (x2). -- **[LIFX Z](https://www.lifx.com/products/lifx-z-starter-kit-without-homekit)** light strip without HomeKit as ceiling wash lights (x3) and bed underglow (x2) -- **[Milight CCT LED RF Controller](https://www.futlight.com/productdetails.aspx?id=293&typeid=146)** for white-adjustable undercabinet kitchen lights (x4), connected to appropriate Ul-listed power supplies. +- **[LIFX Z](https://www.lifx.com/products/lifx-z-starter-kit-without-homekit)** light strip without HomeKit as bed underglow (x2) and ceiling wash lights (x3). +- **[Milight CCT LED RF Controller](https://www.futlight.com/productdetails.aspx?id=293&typeid=146)** for white-adjustable undercabinet kitchen lights (x4), connected to appropriate UL-listed power supplies. - **[24V 3014 Warm White Cool White LED Strip](http://ledmontreal.com/en/led-strips-without-accessories/24v-led-strips-without-accessories/cct-adjustable-led-strip.html)** encased in custom cut and assembled [light-diffusing aluminum profiles](http://ledmontreal.com/en/led-bars-and-profiles-led-montreal/continuous-lighting-aluminum-profile.html), connected to above RF controllers. -- **[Flic](https://flic.io)** bluetooth low energy buttons. +- **[Adalight](https://learn.adafruit.com/adalight-diy-ambient-tv-lighting)** DIY 100-dots TV backlighting controlled by [Lightpack+Prismatik](https://github.com/psieg/Lightpack) on HTPC. +- **Fairy lights** via TP-Link wifi outlets (x3). +- **DIY LED nightstand** via TP-Link wifi outlet. + + +#### Sensors - **[Aeotec Door / Window Sensor Gen5](https://aeotec.com/z-wave-door-window-sensor)** for front door. - **[Aeotec MultiSensor 6](https://aeotec.com/z-wave-sensor)** for temperature/humidity/presence detection. -- **[Adalight](https://learn.adafruit.com/adalight-diy-ambient-tv-lighting)** DIY 100-dots TV backlighting controlled by [Lightpack+Prismatik](https://github.com/psieg/Lightpack) on HTPC. - **[AcuRite 06044M Wireless Sensor](https://www.acurite.com/indoor-temperature-sensor-and-humidity-gauge.html)** for cheap temperature and humidity monitoring. + + +#### Human Interfaces +- **[Acer Iconia One 10" tablet](https://www.acer.com/ac/en/CA/content/series/iconiaone10)** (1280x800 IPS screen) wallmounted as a kiosk. See [`/appdaemon/dashboards/`](appdaemon/dashboards). +- **[Aeotec Minimote](https://www.youtube.com/watch?v=5Vc1Ift7ND8)** Z-Wave remote control. +- **[Flic](https://flic.io)** bluetooth low energy buttons. + + +#### Switches and other devices - **[TP-Link Smart Wi-Fi Plug Mini outlets](http://www.tp-link.com/us/products/details/cat-5516_HS105.html)** to control dumb devices (x6). - **[Frigidaire dehumidifier](http://www.dehumidifierbuyersguide.com/frigidaire-ffad7033r1-review)** via TP-Link wifi outlet. - **Oscillating fan** via TP-Link wifi outlet. -- **Fairy lights** via TP-Link wifi outlets (x3). -- **DIY LED nightstand** via TP-Link wifi outlet. + ### Software - **[Hass.io](https://home-assistant.io)** on Raspberry Pi (production setup). -- **[Docker](https://www.docker.com)** on local machine (for development). +- **[Docker](https://www.docker.com)** on local machine (for development). True, Hass.io is Docker-based too... 😉 +- **[Fully Kiosk Browser](https://www.ozerov.de/fully-kiosk-browser/)** on wallmounted tablet for display and input. +- **[LANnouncer](http://www.keybounce.com/lannouncer/)** on wallmounted tablet for simple audio and text-to-speech messaging. + -### Hass.io add-ons -- **[AppDaemon2](https://github.com/home-assistant/appdaemon)** for HADashboard tablet UI. +#### Hass.io add-ons +- **[AppDaemon](https://github.com/home-assistant/appdaemon)** for HADashboard tablet UI. - **[Bluetooth BCM43xx](https://home-assistant.io/addons/bluetooth_bcm43xx)** to use Raspberry Pi's bluetooth. - **[Flicd](https://github.com/pschmitt/hassio-addons)** to connect with Flic bluetooth buttons. -- **[Mosquitto MQTT broker](https://home-assistant.io/addons/mosquitto)** for standard IoT messaging. - **[Homebridge](https://github.com/hassio-addons/addon-homebridge)** to control non-HomeKit compatible devices using iPhones. +- **[Mosquitto MQTT broker](https://home-assistant.io/addons/mosquitto)** for standard IoT messaging. - **[RTL_433 to MQTT Bridge](https://github.com/james-fry/hassio-addons)** to receive and decode AcuRite radio signals. - **[Samba share](https://home-assistant.io/addons/samba)** for configuration file sharing. +- **[SSH server](https://home-assistant.io/addons/ssh)** for command-line access. -### Community components and widgets + +#### Community components and widgets - **[Custom UI elements](https://github.com/andrey-git/home-assistant-custom-ui)** to improve the display of sensors and jazz up the interface a bit. +- **[Display](https://github.com/daemondazz/homeassistant-displays)** platform for integration with the Fully Kiosk Browser.. - **[Horizontal line state card](https://github.com/covrig/homeassistant-hline)** to visually separate long lists of sensors. -- **[Text-only state card](https://community.home-assistant.io/t/display-only-text-in-card/20536/26)** for wordy sensor states. -- **[Nanoleaf Aurora](https://github.com/software-2/ha-aurora)** ([Fork](https://github.com/Oro/home-assistant/tree/light-aurora)) component. - **[Lightpack](https://github.com/kklemm91/Lightpack-HASS)** component. +- **[Nanoleaf Aurora](https://github.com/software-2/ha-aurora)** ([Fork](https://github.com/Oro/home-assistant/tree/light-aurora)) component. +- **[Text-only state card](https://community.home-assistant.io/t/display-only-text-in-card/20536/26)** for wordy sensor states. +- **[Variable](https://github.com/rogro82/hass-variables)** component for non-boolean values. ## Thanks Kudos to: -- **The [dedicated core team](https://home-assistant.io/blog)** that builds and manages Home Assistant, they work fast and humbly. +- **The [dedicated core team](https://home-assistant.io/blog)** that builds and manages Home Assistant. They work fast and humbly. - **The horde of volunteer developers** of all components and add-ons. - **The [vibrant community](https://community.home-assistant.io)**, always willing to help and share code samples. - **The [BRUH Automation](https://www.youtube.com/c/bruhautomation1) YouTube channel**, Ben's videos got me hooked on using Home Assistant. -Thank you for all your dedication, helpfulness and valuable insights. Cheers! :-) +Thank you for all your dedication, helpfulness and valuable insights. Cheers! 🍻😃 [img-travis-ci]:https://img.shields.io/travis/renemarc/home-assistant-config.svg?branch=master&logo=travis -[img-github-release]:https://img.shields.io/github/release/renemarc/home-assistant-config/all.svg?logo=github +[img-github-release]:https://img.shields.io/github/release/renemarc/home-assistant-config/all.svg [img-repo-size]:https://img.shields.io/github/repo-size/renemarc/home-assistant-config.svg [img-code-size]:https://img.shields.io/github/languages/code-size/renemarc/home-assistant-config.svg -[img-hassio]:https://img.shields.io/badge/Config_for-Hass.io-53c1f1.svg +[img-ha-version]:https://img.shields.io/badge/tested_on_Home_Assistant-0.66.1-53c1f1.svg +[img-hassio]:https://img.shields.io/badge/config_for-Hass.io-53c1f1.svg [img-license]:https://img.shields.io/github/license/renemarc/home-assistant-config.svg [link-repo]:https://github.com/renemarc/home-assistant-config +[link-issues]:https://github.com/renemarc/home-assistant-config/issues +[link-board]:https://github.com/renemarc/home-assistant-config/projects/1 [link-travis-ci]:https://travis-ci.org/renemarc/home-assistant-config [link-hassio]:https://home-assistant.io/hassio/ +[link-ha-version]:https://www.home-assistant.io/blog/2018/03/30/release-66/ [link-license]:LICENSE.txt diff --git a/appdaemon/README.md b/appdaemon/README.md index 7f028a4..1ad0557 100644 --- a/appdaemon/README.md +++ b/appdaemon/README.md @@ -1,21 +1,22 @@ -# AppDaemon 2.0 configuration +# AppDaemon 3.0 configuration +## Folders -## [`apps`](apps) +### [`📂 ./apps/`](apps) Empty, to be used for eventual AppDaemon apps. -## [`custom_css`](custom_css/modern) +### [`🌈 ./custom_css/`](custom_css/modern) For the **Modern** theme. -## [`custom_widgets`](custom_widgets) +### [`🔘 ./custom_widgets/`](custom_widgets) For third-party, custom and modified dashboard widgets. -## [`dashboards`](dashboards) +### [`🖼 ./dashboards/`](dashboards) For the dashboards used in HADashboard. diff --git a/appdaemon/appdaemon.yaml b/appdaemon/appdaemon.yaml index 8c1178d..e329381 100644 --- a/appdaemon/appdaemon.yaml +++ b/appdaemon/appdaemon.yaml @@ -1,11 +1,17 @@ -AppDaemon: +secrets: /config/secrets.yaml +log: logfile: STDOUT errorfile: STDERR +appdaemon: threads: 10 app_dir: /config/appdaemon/apps disable_apps: 1 -HASS: - ha_url: http://homeassistant:8123 -HADashboard: - dash_url: http://127.0.0.1:5050 + plugins: + HASS: + type: hass + ha_url: http://hassio/homeassistant + ha_key: f411986db776442b864aa2a31f2d948c +hadashboard: + dash_url: !secret hadashboard_dash_url dash_dir: /config/appdaemon/dashboards + dash_compile_on_start: 1 diff --git a/appdaemon/apps.yaml b/appdaemon/apps.yaml deleted file mode 100644 index e69de29..0000000 diff --git a/appdaemon/custom_css/modern/README.md b/appdaemon/custom_css/modern/README.md index 529a1b8..36c2656 100644 --- a/appdaemon/custom_css/modern/README.md +++ b/appdaemon/custom_css/modern/README.md @@ -1,3 +1,3 @@ # AppDaemon _Modern_ custom theme -This theme is based very closely on the [default](https://github.com/home-assistant/appdaemon/tree/dev/appdaemon/assets/css/default) one, except with some minor tweaks to the CSS and extra classes and variables to support [`/appdaemon/custom_widgets`](../custom_widgets). +This theme is based very closely on the [default](https://github.com/home-assistant/appdaemon/tree/master/appdaemon/assets/css/default) one, except with some minor tweaks to the CSS and extra classes and variables to support [`/appdaemon/custom_widgets/`](../../custom_widgets). diff --git a/appdaemon/custom_css/modern/variables.yaml b/appdaemon/custom_css/modern/variables.yaml index e23204e..af57571 100644 --- a/appdaemon/custom_css/modern/variables.yaml +++ b/appdaemon/custom_css/modern/variables.yaml @@ -43,7 +43,37 @@ head_includes: # body_includes: - - + - | + # # Styles diff --git a/appdaemon/custom_widgets/README.md b/appdaemon/custom_widgets/README.md index 2b61126..308f8c7 100644 --- a/appdaemon/custom_widgets/README.md +++ b/appdaemon/custom_widgets/README.md @@ -1,31 +1,99 @@ # Custom AppDaemon widgets -AppDaemon offers [many widgets](https://github.com/home-assistant/appdaemon/tree/dev/appdaemon/widgets/), but can support some third-party and custom ones. +[AppDaemon](https://home-assistant.io/docs/ecosystem/appdaemon/) offers [many default widgets](https://github.com/home-assistant/appdaemon/tree/master/appdaemon/widgets/), but can also support third-party and custom ones. ## Community widgets -- [`baseiconsensor`](baseentitydisplay) from [ReneTode's repo]([)https://github.com/ReneTode/My-AppDaemon/tree/master/custom_widgets), modified with: - + Support for entities used as **title** and **title2**. +### [`💡 iconsensor.yaml`](iconsensor.yaml) and [`baseiconsensor`](baseiconsensor) -- [`baseselect`](baseentitydisplay) also from [ReneTode's repo](https://github.com/ReneTode/My-AppDaemon/tree/master/custom_widgets), modified with: - + Support for **sub_entities**. +Icon widget from [ReneTode's repo](https://github.com/ReneTode/My-AppDaemon/tree/master/custom_widgets/baseiconsensor), modified with: +- Added support for entities used as **title** and **title2**. + +
+
+
+ Icon sensor widget +
+
+

Icon sensor widget with title2 entity.

+
+
+
+ + +### [`🔘 input_select.yaml`](input_select.yaml) and [`baseselect`](baseselect) + +Selector widget also from [ReneTode's repo](https://github.com/ReneTode/My-AppDaemon/tree/master/custom_widgets/baseselect), modified with: +- Added support for **sub_entities**. + +
+
+
+ Input selectwidget +
+
+

Input select widget with sub entity.

+
+
+
## Custom widgets -- [`baseentitydisplay`](baseentitydisplay) is based on the default [basedisplay](https://github.com/home-assistant/appdaemon/tree/dev/appdaemon/widgets/basedisplay) but with the following modifications: - + Support for entities used as **title** and **title2**. - + Include **unit_of_measurement** to the **sub_entity**, if any. +### [`👽 entitysensor.yaml`](entitysensor.yaml) and [`baseentitydisplay`](baseentitydisplay) + +Multipurpose widget based on the default [basedisplay](https://github.com/home-assistant/appdaemon/tree/master/appdaemon/widgets/basedisplay) but with the following modifications: +- Support for entities used as **title** and **title2**. +- Include **unit_of_measurement** to the **sub_entity**, if any. + +
+
+
+ Entity sensor widget +
+
+

Entity sensor widget with title2 entity.

+
+
+
+ + +### [`📸 entitycamera.yaml`](entitycamera.yaml) and [`baseentityiframe`](baseentityiframe) + +IFrame widget to showcase images and slideshows, based on the default [baseiframe](https://github.com/home-assistant/appdaemon/tree/master/appdaemon/widgets/baseiframe) but includes: +- Cache-buster added to already parameterized URLs. +- Optional **cache** integer parameter to add longevity to the cache-buster JS parameter. +- Optional entity dynamic titles, where an image can have a related title shown if it has a companion entity that provides such textual information. + +
+
+
+ Entity camera widget +
+
+

Entity camera widget with dynamic titles.

+
+
+
+ -- [`baseentityiframe`](baseentityiframe) is based on the default [baseiframe](https://github.com/home-assistant/appdaemon/tree/dev/appdaemon/widgets/baseiframe) but includes: - + Cache-buster added to already parameterized URLs. - + Optional **cache** integer parameter to add longevity to the cache-buster JS parameter. +### [`📶 multisensor.yaml`](multisensor.yaml) and [`basemultisensor`](basemultisensor) +Multi-sensors widget, like the **entitysensor** above, but adds: +- List two sensors size by side (useful to showcase both _temperature_ and _humidity_ together). -- [`basemultisensor`](basemultisensor) is like **baseentitydisplay** above, but adds: - + List two sensors size by side (useful to showcase both _temperature_ and _humidity_ together). +
+
+
+ Multisensor widget +
+
+

Multisensor widget with temperature and humidity.

+
+
+
-## Configuration +## Customization -The extra styling of these widgets is done in the theme [`/appdaemon/custom_css/modern`](../custom_css/modern) as well as directly in [`/appdaemon/dashboards`](../dashboards). +The extra styling of these widgets is done in the theme [`/appdaemon/custom_css/modern/`](../custom_css/modern) as well as directly in [`/appdaemon/dashboards/`](../dashboards). diff --git a/appdaemon/custom_widgets/baseentityiframe/baseentityiframe.js b/appdaemon/custom_widgets/baseentityiframe/baseentityiframe.js index 854f70a..b1fbc3a 100644 --- a/appdaemon/custom_widgets/baseentityiframe/baseentityiframe.js +++ b/appdaemon/custom_widgets/baseentityiframe/baseentityiframe.js @@ -1,14 +1,54 @@ function baseentityiframe(widget_id, url, skin, parameters) { - self = this + self = this; // Initialization self.parameters = parameters; - var callbacks = [] + var callbacks = []; - var monitored_entities = [] + var monitored_entities = []; + + var _titles = []; + + // Define dynamic methods. + if ("title_entity_list" in self.parameters) + { + function record_title_value(self, state, idx) + { + _titles[idx] = state.state; + } + self.record_title_value = record_title_value; + + self.title_index = 0; + + // Set title entities changes to be recorded. + var nameAvailable, nameUpdate, funcAvailable, funcUpdate, + title_size = self.parameters.title_entity_list.length; + + for (var i = 0; i < title_size; ++i) + { + _titles[i] = ''; + entity_title = self.parameters.title_entity_list[i]; + if (entity_title.trim() != "") { + nameAvailable = "OnTitle" + self.title_index + "StateAvailable"; + funcAvailable = new Function( + "return function " + nameAvailable + "(self, state){ self.record_title_value(self, state, " + self.title_index + ");}" + )(); + Object.defineProperty(self, nameAvailable, {value: funcAvailable, writable: false}); + + nameUpdate = "OnTitle" + self.title_index + "StateUpdate"; + funcUpdate = new Function( + "return function " + nameUpdate + "(self, state){ self.record_title_value(self, state, " + self.title_index + ");}" + )(); + Object.defineProperty(self, nameUpdate, {value: funcUpdate, writable: false}); + + monitored_entities.push({"entity": entity_title, "initial": self[nameAvailable], "update": self[nameUpdate]}); + } + self.title_index = self.title_index + 1; + } + } // Call the parent constructor to get things moving @@ -34,9 +74,10 @@ function baseentityiframe(widget_id, url, skin, parameters) { self.set_field(self, "frame_src", self.parameters.url_list[self.index]); self.set_field(self, "img_src", "/images/Blank.gif"); + self.set_field(self, "title", _titles[self.index]); size = self.parameters.url_list.length } - else if ("img_list" in self.parameters) + else if ("img_list" in self.parameters) { var url = self.parameters.img_list[self.index]; var separator = url.indexOf('?') > -1 ? '&' : '?'; @@ -44,6 +85,7 @@ function baseentityiframe(widget_id, url, skin, parameters) var timestamp = Math.floor(date/1000) - (self.cache ? Math.floor(date/1000) % self.cache : 0); url = url + separator + "time=" + timestamp; self.set_field(self, "img_src", url); + self.set_field(self, "title", _titles[self.index]); size = self.parameters.img_list.length } else if ("entity_picture" in self.parameters) diff --git a/appdaemon/dashboards/Main.dash b/appdaemon/dashboards/Main.dash index 8886d9f..52097ca 100644 --- a/appdaemon/dashboards/Main.dash +++ b/appdaemon/dashboards/Main.dash @@ -68,20 +68,16 @@ slideshow: widget_type: entitycamera refresh: 5 img_list: - - http://hassio.local:8123/api/camera_proxy/camera.bing_wallpaper?token=bc9ccd0575dfb05d63df105cc8ed76d6578d63e60083e48fe265a07513a9861d - http://hassio.local:8123/api/camera_proxy/camera.environment_canada_snow?token=72401f9a299bbf9f8521bd46bb8e2366d29d59af19006522910aaed73502cb47 - - http://hassio.local:8123/api/camera_proxy/camera.astronomy_picture_of_the_day?token=8a93f72de0a6538bd4c8348a338bd13a65be0bab41545f1b2f97676fb584c150 + - http://hassio.local:8123/api/camera_proxy/camera.bing_wallpaper?token=bc9ccd0575dfb05d63df105cc8ed76d6578d63e60083e48fe265a07513a9861d - http://hassio.local:8123/api/camera_proxy/camera.noaa_geocolor?token=c5c3e871bce6c743f4bb50b41cfed061fb9ac474735d22710d6d44d23725a961 - -slideshow_apod: - widget_type: sensor - entity: sensor.apod_title - widget_style: "background-color:inherit;" - -slideshow_bing: - widget_type: sensor - entity: sensor.bing_wallpaper_info - widget_style: "background-color:inherit;" + - http://hassio.local:8123/api/camera_proxy/camera.astronomy_picture_of_the_day?token=8a93f72de0a6538bd4c8348a338bd13a65be0bab41545f1b2f97676fb584c150 + title_entity_list: + - "" + - sensor.bing_wallpaper_info + - "" + - sensor.apod_info + title_style: "line-height:2em;opacity:0.8;" # @@ -114,6 +110,14 @@ night_mode: entity: input_boolean.night_mode title2: Go to sleep +scene: + widget_type: input_select + title2: Set a scene + entity: input_select.scene + sub_entity: input_select.scene + state_text_style: "background-color:#555;" + select_style: "background-color:#555;color:$white;" + # # Weather @@ -237,6 +241,6 @@ layout: - nav_main, label(6x1), reload, temperature, clock - nav_switchboard, slideshow(6x4), wind, temperature_now, weather_icon_now - nav_weather, outdoor_safety, daily_forecast(2x1) - - nav_spacer(1x2), slideshow_bing, to_metro, to_market - - slideshow_apod, to_metro_2, to_market_2 - - nav_status, good_morning, night_mode, nap_mode, quiet_mode, low_power_mode, spacer(2x1), to_metro_3, to_market_3 + - nav_spacer(1x2), spacer, to_metro, to_market + - spacer, to_metro_2, to_market_2 + - nav_status, good_morning, night_mode, nap_mode, scene, quiet_mode, low_power_mode, spacer, to_metro_3, to_market_3 diff --git a/appdaemon/dashboards/README.md b/appdaemon/dashboards/README.md index eed01c5..5b07ccc 100644 --- a/appdaemon/dashboards/README.md +++ b/appdaemon/dashboards/README.md @@ -1,4 +1,4 @@ -# AppDaemon 2.0 dashboards +# AppDaemon 3.0 dashboards These are dashboards to be used in a wall-mounted tablet to control Home Assistant the same way you would on a computer, only in a more appropriate interface for casual and often-on display. @@ -11,7 +11,7 @@ These dashboards target a 10" display tablet with 1024x800 resolution using a fu ## Organization -Dashboards are split into 4 pages, organized in a similar fashion as [`/groups`](../../groups) only with less administrative features and prettier colours. +Dashboards are split into 4 pages, organized in a similar fashion as [`/groups/`](../../groups) only with less administrative features and prettier colours. ### Fixed elements @@ -19,28 +19,72 @@ Dashboards are split into 4 pages, organized in a similar fashion as [`/groups`] The top menu and left-hand navigation are fixed. The navigation colours change depending on which dashboard you're on and the top menu title changes accordingly. That makes navigation intuitive for anyone. -### Main dashboard +### [`🏠 ./Main.dash`](Main.dash) -With a feel-good welcome message, common actions, quick weather status, bus schedules, and rotating set of weather radar, satellite maps and pretty pictures of the day. +With a feel-good welcome message, common actions, quick weather status, bus schedules, and rotating set of weather radar, satellite map and pretty pictures of the day. +
+
+
+ Main dashboard +
+
+ Main dashboard. +
+
+
-### Switchboard + +### [`🔘 ./Switchboard.dash`](Switchboard.dash) Organized my room and control zone, including climate control. Looks kind of like Tetris! :-) +
+
+
+ Switchboard +
+
+ Switchboard, with placeholders for planned devices. +
+
+
+ -### Weather +### [`🌦 ./Weather.dash`](Weather.dash) -With current conditions, forecasts, air quality, and rotating satellite maps and animated radar maps. +With current conditions, forecasts, air quality, and rotating satellite images and animated radar maps. +
+
+
+ Weather dashboard +
+
+ Weather dashboard. +
+
+
-### Status + +### [`👀 ./Status.dash`](Status.dash) Geeky details about Home Assistant, network, battery status and per-location temperature and humidity. +
+
+
+ Status dashboard +
+
+ Status dashboard. +
+
+
+ ## Theme -The [`/appdeamon/custom_css/modern`](../custom_css/modern) theme is based on an adapted version of the default theme. Only some CSS rules differ, in addition to support for third-party and custom widgets. +The [`/appdaemon/custom_css/modern/`](../custom_css/modern) theme is based on an adapted version of the default theme. Only some CSS rules differ, in addition to support for third-party and custom widgets. The contents of many tiles depend on specific [template sensors](../../sensors) to make information easier to digest. diff --git a/appdaemon/dashboards/Status.dash b/appdaemon/dashboards/Status.dash index 0abb3f0..27f80f8 100644 --- a/appdaemon/dashboards/Status.dash +++ b/appdaemon/dashboards/Status.dash @@ -81,35 +81,35 @@ database_size: title: Database entity: sensor.database_size -logfile_size: +log_size: widget_type: sensor title: Log File - entity: sensor.logfile_size + entity: sensor.log_size cpu_temp: widget_type: sensor entity: sensor.cpu_temp title: CPU Temp -cpu_used: +cpu_use: widget_type: sensor - entity: sensor.cpu_used + entity: sensor.processor_use sub_entity: sensor.average_load - title: CPU Used + title: CPU Load state_text_style: "background-color:#555;" -ram_used: +memory_use: widget_type: entitysensor - entity: sensor.ram_used_percent - sub_entity: sensor.ram_used - title: RAM Used + entity: sensor.memory_use_percent + sub_entity: sensor.memory_use + title: Memory Use state_text_style: "background-color:#555;" -disk_used: +disk_use: widget_type: entitysensor - entity: sensor.disk_used_percent - sub_entity: sensor.disk_used_home - title: Disk Used + entity: sensor.disk_use_percent + sub_entity: sensor.disk_use_home + title: Disk Use state_text_style: "background-color:#555;" @@ -188,13 +188,20 @@ lounge_humidity: # # Battery # +kiosk_battery: + widget_type: sensor + entity: sensor.kiosk_battery + title: Battery Status + title2: Kiosk + widget_style: "background-color:inherit;" + title_style: "background-color:#555;padding:5px 156% 3px;margin-right:-10px;margin-top:-5px;border-radius: 5px 5px 0 0" + title2_style: "margin-top:3px;" + front_door_sensor_battery: widget_type: sensor entity: sensor.front_door_sensor_battery - title: Battery Status title2: Front Door widget_style: "background-color:inherit;" - title_style: "background-color:#555;padding:5px 104% 3px;margin-right:-10px;margin-top:-5px;border-radius: 5px 5px 0 0" title2_style: "margin-top:3px;" bedroom_multisensor_battery: @@ -212,15 +219,35 @@ lounge_multisensor_battery: title2_style: "margin-top:3px;" +# +# Security +# +status_doors: + widget_type: binary_sensor + entity: input_boolean.doors_open + title: Doors + icon_on: mdi-lock-open-outline + icon_off: mdi-lock + +status_motion: + widget_type: binary_sensor + entity: input_boolean.motion_detected + title: Motion + +status_tamper: + widget_type: binary_sensor + entity: input_boolean.tamper_detected + title: Tampering + + # # Layout # layout: - - include: header - include: header - nav_main, label(6x1), reload, temperature, clock - - nav_switchboard, uptime, uptime_host, database_size, logfile_size - - nav_weather, cpu_temp, cpu_used, ram_used, disk_used, spacer(2x1), sensor.speedtest_ping, upspeed, downspeed + - nav_switchboard, uptime, uptime_host, database_size, log_size, spacer(2x1), status_doors, status_motion, status_tamper + - nav_weather, cpu_temp, cpu_use, memory_use, disk_use, spacer(2x1), sensor.speedtest_ping, upspeed, downspeed - nav_spacer(1x2) - - average_temperature, bedroom_temperature, lounge_temperature, spacer(3x1), front_door_sensor_battery, bedroom_multisensor_battery, lounge_multisensor_battery + - average_temperature, bedroom_temperature, lounge_temperature, spacer(2x1), kiosk_battery, front_door_sensor_battery, bedroom_multisensor_battery, lounge_multisensor_battery - nav_status, average_humidity, bedroom_humidity, lounge_humidity diff --git a/appdaemon/dashboards/Switchboard.dash b/appdaemon/dashboards/Switchboard.dash index 8a68621..32267ed 100644 --- a/appdaemon/dashboards/Switchboard.dash +++ b/appdaemon/dashboards/Switchboard.dash @@ -114,7 +114,6 @@ washlight_lounge: # # Climate # - label_climate: widget_type: multisensor title2: Climate @@ -143,7 +142,6 @@ switch_air_filter: # # Kitchen # - label_kitchen: widget_type: label title2: Kitchen @@ -178,7 +176,6 @@ light_sink: # # Washroom # - label_washroom: widget_type: label title2: Toilet @@ -200,10 +197,10 @@ spacer_tetris: widget_type: label widget_style: "background-color:ROYALBLUE;" + # # Bedroom # - label_bedroom: widget_type: multisensor title2: Bedroom @@ -255,7 +252,6 @@ fan_bedroom: # # Lounge # - label_lounge: widget_type: multisensor title2: Lounge @@ -282,10 +278,19 @@ light_aurora_effect: light_tv_backlight: widget_type: switch - title: TV Backlight + title: Lightpack entity: light.lightpack widget_style: "background-color:DARKRED;" +light_tv_backlight_effect: + widget_type: input_select + title2: Lightpack Effect + entity: input_select.lightpack_effect + sub_entity: sensor.lightpack_effect_loaded + widget_style: "background-color:DARKRED;" + state_text_style: "background-color:FIREBRICK;" + select_style: "background-color:FIREBRICK;color:$white;" + light_spotlight: widget_type: light title: Spotlight @@ -310,39 +315,14 @@ light_window: widget_style: "background-color:DARKRED;" - - - -# switch_washroom: -# widget_type: switch -# entity: group.washroom -# widget_style: "background-color:inherit;" - -# humidity_bedroom: -# widget_type: sensor -# entity: sensor.bedroom_humidity -# widget_style: "background-color:inherit;" -# value_style: "position:absolute;top:-20px;left:0;font-size:200%;" -# unit_style: "position:absolute;top:-23px;" - -# temperature_bedroom: -# widget_type: sensor -# entity: sensor.bedroom_temperature -# widget_style: "background-color:inherit;" -# value_style: "position:absolute;top:-20px;left:0;font-size:200%;color:orange;" -# unit_style: "position:absolute;top:-23px;color:orange;" - - - # # Layout # - layout: - include: header - nav_main, label(6x1), reload, temperature, clock - nav_switchboard, spacer, label_exterior, light_front_porch, spacer(2x1), label_ceiling, washlight_bedroom, washlight_middle, washlight_lounge - nav_weather, label_kitchen, light_microwave, spacer, label_washroom, light_shower, spacer, label_climate, switch_air_filter - nav_spacer(1x2), light_island, light_sink, light_countertop, spacer, light_lavatory, spacer, switch_dehumidifier, switch_humidifier - - label_bedroom, light_bed_effect, underglow_headboard, underglow_underbed, spacer_tetris, label_lounge, light_aurora_effect, light_aurora, light_tv_backlight - - nav_status, light_nightstand, light_bedside, fan_bedroom, spacer(2x1), light_spotlight, light_souvenirs, light_window, light_lamp + - label_bedroom, light_bed_effect, underglow_headboard, underglow_underbed, label_lounge, light_aurora_effect, light_aurora, light_tv_backlight_effect, light_tv_backlight + - nav_status, light_nightstand, light_bedside, fan_bedroom, spacer, light_spotlight, light_souvenirs, light_window, light_lamp diff --git a/appdaemon/dashboards/Weather.dash b/appdaemon/dashboards/Weather.dash index 2c13ceb..248e033 100644 --- a/appdaemon/dashboards/Weather.dash +++ b/appdaemon/dashboards/Weather.dash @@ -255,6 +255,13 @@ aqi_nitrogen_dioxide: sub_entity: sensor.aqi_nitrogen_dioxide_friendly state_text_style: "background-color:#555;" +aqi_sulphur_dioxide: + widget_type: sensor + title: Sulphur Dioxide + entity: sensor.aqi_sulphur_dioxide + sub_entity: sensor.aqi_sulphur_dioxide_friendly + state_text_style: "background-color:#555;" + uv: widget_type: sensor title: UV @@ -272,5 +279,5 @@ layout: - nav_switchboard, camera_noaa(3x3), camera_environment_canada(3x3), wind, daily_forecast(2x1) - nav_weather, wind_icon, weekly_forecast(2x1) - nav_spacer(1x2), spacer, temperature_today, weather_icon_today - - spacer, spacer(6x1), temperature_tomorrow, weather_icon_tomorrow - - nav_status, uv, aqi, aqi_particles, aqi_ozone, aqi_carbon_monoxide, aqi_nitrogen_dioxide, spacer, temperature_after_tomorrow, weather_icon_after_tomorrow + - aqi, uv, sensor.doomsday_clock, spacer(4x1), temperature_tomorrow, weather_icon_tomorrow + - nav_status, aqi_particles, aqi_ozone, aqi_carbon_monoxide, aqi_nitrogen_dioxide, aqi_sulphur_dioxide, spacer(2x1), temperature_after_tomorrow, weather_icon_after_tomorrow diff --git a/automations/README.md b/automations/README.md index 99aa78c..b36be0d 100644 --- a/automations/README.md +++ b/automations/README.md @@ -4,7 +4,7 @@ To prevent _spaghettification_ of automations as this project grows, I employ a [publish–subscribe pattern](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern) (kind of a lightweight [mediator pattern](https://en.wikipedia.org/wiki/Mediator_pattern)) where some automations will trigger changes on [`/misc/input_booleans.yaml`](../misc/input_booleans.yaml) and [`/misc/variables.yaml`](../misc/variables.yaml) while others listen to those changes. -For example, one push of a button will lead to enabling the **sleep mode** by setting the relevant boolean to _true_. Every room has an automation that listens to changes on that **sleep mode** boolean, and is responsible for turning devices on and off accordingly. This makes every room reactive to one central direction, without having to maintain a monolithic [`/scripts/go_to_sleep.yaml`](../scripts/go_to_sleep.yaml) that lists all the devices that must be acted upon. +For example, one push of a button will lead to enabling the **night mode** by setting the relevant boolean to _true_. Every room has an automation that listens to changes on that **night mode** boolean, and is responsible for turning devices on and off accordingly. This makes every room reactive to one central direction, without having to maintain a monolithic [`/scripts/go_to_sleep.yaml`](../scripts/go_to_sleep.yaml) that lists all the devices that must be acted upon. It's a bit like a boss giving orders to managers, and letting them figure out how to best accomplish these goals based on what they know about their respective teams. Less micromanagement = smarter teams. diff --git a/automations/aurora_brightness.yaml b/automations/aurora_brightness.yaml index f1cf773..1817bae 100644 --- a/automations/aurora_brightness.yaml +++ b/automations/aurora_brightness.yaml @@ -16,6 +16,8 @@ action: # Set the Aurora's brightness according to the new level. - service: light.turn_on + data: + entity_id: + - light.aurora data_template: - entity_id: light.aurora brightness: "{{ states('variable.aurora_brightness') }}" diff --git a/automations/aurora_default.yaml b/automations/aurora_default.yaml deleted file mode 100644 index eb364d4..0000000 --- a/automations/aurora_default.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# -# Return the Aurora to its default scheduled effect -# -# By removing the manual override, the Aurora will automatically fall back to -# the regularly schedule effect. -# -# @subscribe variable.aurora_effect -# -# @publish input_boolean.aurora_effect_override -# -# @see /automations/aurora_schedule.yaml -# -- id: aurora_default - alias: Aurora DEFAULT - trigger: - # If the default effect is selected. - - platform: state - entity_id: input_select.aurora_effect - to: Auto - - action: - # Remove the Aurora effect override. - - service: input_boolean.turn_off - entity_id: input_boolean.aurora_effect_override diff --git a/automations/aurora_effect.yaml b/automations/aurora_effect.yaml index 104be6e..39905c4 100644 --- a/automations/aurora_effect.yaml +++ b/automations/aurora_effect.yaml @@ -21,7 +21,8 @@ action: # Set the Aurora's internal effect according to the received name. - service: light.turn_on - data_template: + data: entity_id: - light.aurora + data_template: effect: "{{ states('variable.aurora_effect') }}" diff --git a/automations/aurora_schedule.yaml b/automations/aurora_schedule.yaml index 20b9f1a..78720b8 100644 --- a/automations/aurora_schedule.yaml +++ b/automations/aurora_schedule.yaml @@ -1,14 +1,16 @@ # -# Schedule the Nanoleaf Aurora based on its loaded-in effects. +# Schedule the Nanoleaf Aurora based on its loaded-in effects # # Unless an effect is manually selected, this scheduler will do its thing. # +# @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode +# @subscribe input_boolean.scene_mode +# @subscribe input_select.aurora_effect +# # @publish variable.aurora_brightness # @publish variable.aurora_effect # -# @subscribe input_boolean.aurora_effect_override -# @subscribe input_boolean.scene_mode -# # @see /automations/aurora_effect.yaml # # @link https://forum.nanoleaf.me/docs/openapi @@ -32,10 +34,10 @@ entity_id: input_boolean.scene_mode to: 'off' - # When Aurora effect override is being released. + # When the selected effect is switched to default. - platform: state - entity_id: input_boolean.aurora_effect_override - to: 'off' + entity_id: input_select.aurora_effect + to: 'Auto' condition: # If automation was not trigered lately (debounce). @@ -51,22 +53,22 @@ entity_id: light.aurora state: 'on' - # If no effect overrides are in place. + # If the selected effect is the default. - condition: state - entity_id: input_boolean.aurora_effect_override - state: 'off' + entity_id: input_select.aurora_effect + state: 'Auto' # If no scenes are enabled. - condition: state entity_id: input_boolean.scene_mode state: 'off' - # Not during the night mode. + # If it's not during the night mode. - condition: state entity_id: input_boolean.night_mode state: 'off' - # Not during the nap mode. + # If it's not during the nap mode. - condition: state entity_id: input_boolean.nap_mode state: 'off' diff --git a/automations/aurora_select.yaml b/automations/aurora_select.yaml index f894fae..5bf3102 100644 --- a/automations/aurora_select.yaml +++ b/automations/aurora_select.yaml @@ -1,5 +1,5 @@ # -# Manually select a Nanoleaf Aurora built-in effect. +# Manually select a Nanoleaf Aurora built-in effect # # @subscribe input_select.aurora_effect # @@ -10,20 +10,23 @@ - id: aurora_select alias: Aurora SELECT trigger: - # An effect has been selected. + # When an effect has been selected. - platform: state entity_id: input_select.aurora_effect + # When an item which was off or physically disconnected comes back online. + - platform: state + entity_id: + - light.aurora + from: 'off' + condition: # If an actual effect is selected, not the default. - condition: template - value_template: "{% if not is_state('input_select.aurora_effect', 'Auto') %}true{% endif %}" + value_template: >- + {{ not is_state('input_select.aurora_effect', 'Auto') }} action: - # Prevent the Aurora scheduler from replacing the selected effect. - - service: input_boolean.turn_on - entity_id: input_boolean.aurora_effect_override - # Update the Aurora effect variable. - service: variable.set_variable data: diff --git a/automations/bed_default.yaml b/automations/bed_default.yaml deleted file mode 100644 index e603e5d..0000000 --- a/automations/bed_default.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# -# Return the bed underglow lights to the default scheduled effect. -# -# By removing the manual override, the bed lights will automatically fall back -# to the regularly schedule effect. -# -# @subscribe variable.bed_effect -# -# @see /automations/bed_schedule.yaml -# @see /scenes/lifx_cloud.yaml -# -- id: bed_default - alias: Bed DEFAULT - trigger: - # If the default effect is selected. - - platform: state - entity_id: input_select.bed_effect - to: Auto - - action: - # Remove the effect override. - - service: input_boolean.turn_off - entity_id: input_boolean.bed_effect_override diff --git a/automations/bed_effect.yaml b/automations/bed_effect.yaml index bb71195..45248b0 100644 --- a/automations/bed_effect.yaml +++ b/automations/bed_effect.yaml @@ -1,5 +1,5 @@ # -# Change bed underglow lights based on Lifx Cloud scenes. +# Change bed underglow lights based on Lifx Cloud scenes # # The LIFX strips have effects programmed with the LIFX mobile and stored on # their servers. Each effect mentions which device will receive which color diff --git a/automations/bed_schedule.yaml b/automations/bed_schedule.yaml index 8ff7343..36716e5 100644 --- a/automations/bed_schedule.yaml +++ b/automations/bed_schedule.yaml @@ -3,9 +3,12 @@ # # Unless an effect is manually selected, this scheduler will do its thing. # -# @publish variable.bed_effect -# @subscribe input_boolean.bed_effect_override +# @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode # @subscribe input_boolean.scene_mode +# @subscribe input_select.bed_effect +# +# @publish variable.bed_effect # # @see /automations/bed_effect.yaml # @@ -35,13 +38,13 @@ entity_id: input_boolean.scene_mode to: 'off' - # When bed underglow lights effect override is being released. + # When the selected effect is switched to default. - platform: state - entity_id: input_boolean.bed_effect_override - to: 'off' + entity_id: input_select.bed_effect + to: 'Auto' condition: - # If automation was not trigered lately. + # If automation was not trigered lately. - condition: template value_template: >- {% set current = as_timestamp(utcnow()) %} @@ -51,25 +54,25 @@ # If bed lights are on. - condition: state - entity_id: group.bed + entity_id: group.bed_lights state: 'on' - # If no effect overrides are in place. + # If the selected effect is the default. - condition: state - entity_id: input_boolean.bed_effect_override - state: 'off' + entity_id: input_select.bed_effect + state: 'Auto' # If no scenes are enabled. - condition: state entity_id: input_boolean.scene_mode state: 'off' - # Not during the night mode. + # If it's not during the night mode. - condition: state entity_id: input_boolean.night_mode state: 'off' - # Not during the nap mode. + # If it's not during the nap mode. - condition: state entity_id: input_boolean.nap_mode state: 'off' diff --git a/automations/bed_select.yaml b/automations/bed_select.yaml index 34d7a2c..b817bba 100644 --- a/automations/bed_select.yaml +++ b/automations/bed_select.yaml @@ -1,5 +1,7 @@ # -# Manually select a LIFX cloud effect for the bed underglow lights. +# Manually select a LIFX cloud effect for the bed underglow lights +# +# @subscribe input_select.bed_effect # # @publish variable.bed_effect # @@ -8,20 +10,24 @@ - id: bed_select alias: Bed SELECT trigger: - # An effect has been selected. + # When an effect has been selected. - platform: state entity_id: input_select.bed_effect + # When an item which was off comes back online. + - platform: state + entity_id: + - light.headboard + - light.underbed + to: 'on' + condition: # If an actual effect is selected, not the default. - condition: template - value_template: "{% if not is_state('input_select.bed_effect', 'Auto') %}true{% endif %}" + value_template: >- + {{ not is_state('input_select.bed_effect', 'Auto') }} action: - # Prevent the bed scheduler from replacing the selected effect. - - service: input_boolean.turn_on - entity_id: input_boolean.bed_effect_override - # Update the bed effect variable. - service: variable.set_variable data: diff --git a/automations/bedroom_low.yaml b/automations/bedroom_low.yaml index 56d219f..b13d22d 100644 --- a/automations/bedroom_low.yaml +++ b/automations/bedroom_low.yaml @@ -1,5 +1,5 @@ # -# Set bedroom to low-power mode. +# Set bedroom to low-power mode # # @subscribe input_boolean.low_mode # @@ -12,22 +12,21 @@ to: 'on' action: - # Turn on some devices. - - service: homeassistant.turn_on + # Turn off ed underglow lights. + - service: homeassistant.turn_off data: entity_id: - - switch.nightstand_light - - switch.bedside_light + - group.bed_lights + transition: 5 - # Turn off some devices. + # Turn off some binary devices. - service: homeassistant.turn_off entity_id: - switch.bedroom_fan - # Turn off some devices. - - service: light.turn_off + # Turn on some binary devices. + - service: homeassistant.turn_on data: entity_id: - - light.headboard - - light.underbed - transition: 5 + - switch.bedside_light + - switch.nightstand_light diff --git a/automations/bedroom_off.yaml b/automations/bedroom_off.yaml index 2733688..788e61c 100644 --- a/automations/bedroom_off.yaml +++ b/automations/bedroom_off.yaml @@ -1,5 +1,7 @@ # -# Turn off bedroom. +# Turn off bedroom +# +# @subscribe input_boolean.nap_mode # - id: bedroom_off alias: Bedroom OFF @@ -10,15 +12,14 @@ to: 'on' action: - # Turn off smart lights. - - service: light.turn_off + # Turn off bed underglow lights. + - service: homeassistant.turn_off data: entity_id: - - light.headboard - - light.underbed + - group.bed_lights transition: 10 - # Turn off binary devices + # Turn off binary devices. - service: homeassistant.turn_off entity_id: - switch.nightstand_light diff --git a/automations/bedroom_on.yaml b/automations/bedroom_on.yaml index e9ed8f0..6f9ac31 100644 --- a/automations/bedroom_on.yaml +++ b/automations/bedroom_on.yaml @@ -1,5 +1,7 @@ # -# Turn on bedroom. +# Turn on bedroom +# +# @subscribe input_boolean.nap_mode # - id: bedroom_on alias: Bedroom ON @@ -10,12 +12,11 @@ to: 'off' action: - # Turn on smart lights. - - service: light.turn_on + # Turn on bed underglow lights. + - service: homeassistant.turn_on data: entity_id: - - light.headboard - - light.underbed + - group.bed_lights transition: 5 # Turn on binary devices. diff --git a/automations/cct.yaml b/automations/cct_lifx.yaml similarity index 85% rename from automations/cct.yaml rename to automations/cct_lifx.yaml index 19a5ddc..1e876c7 100644 --- a/automations/cct.yaml +++ b/automations/cct_lifx.yaml @@ -1,19 +1,30 @@ # -# Adjust color temperature (CCT) based on cyrcadian rythm. +# Adjust LIFX bulbs color temperature (CCT) based on cyrcadian rythm +# +# LIFX lightbulbs allow their colours to be changed even when their states are +# off, which we use to our advantage by always setting the light to the desired +# conditions. Then, when the light is actually turned on it will already be at +# the right level. # # White temperature is based on a custom curve, not f.lux nor using the sun, # otherwise it would be kind of gloomy to see warm yellows a lot in winter time. # -# Todo: Split LIFX devices from MiLight. +# LIFX+ bulbs white color range: +# Mireds: 111 - 400 +# Kelvins: 9000K - 2500K +# # Todo: User-configurable targets and hours? # Todo: Use sun as basis for color temp boundaries? # Todo: Use sin/cos to determine curve? # +# @subscribe input_boolean.night_mode +# @subscribe input_boolean.scene_mode +# # @link https://community.home-assistant.io/t/lifx-circadian-rhythm-time-of-day-automation/23091 # @link https://sigmaluminous.com/the-circadian-rhythm-and-color-temperature/ # -- id: cct - alias: CCT +- id: cct_lifx + alias: CCT LIFX trigger: # Every five minutes. - platform: time @@ -38,17 +49,17 @@ entity_id: input_boolean.scene_mode state: 'off' - # If no during the night mode. + # If it's not during the night mode. - condition: state entity_id: input_boolean.night_mode state: 'off' action: + # Set light colour and brightness using LIFX service. - service: light.lifx_set_state data: entity_id: - - light.shower - - light.spotlight + - group.lifx_lights data_template: color_temp: > {% set schedule = { diff --git a/automations/cct_limitlessled.yaml b/automations/cct_limitlessled.yaml new file mode 100644 index 0000000..39cf42a --- /dev/null +++ b/automations/cct_limitlessled.yaml @@ -0,0 +1,188 @@ +# +# Adjust LimitlessLED/MiLight color temperature (CCT) based on cyrcadian rythm +# +# White temperature is based on a custom curve, not f.lux nor using the sun, +# otherwise it would be kind of gloomy to see warm yellows a lot in winter time. +# +# Todo: User-configurable targets and hours? +# +# Milight FUT035 controllers color range: +# Mireds: 154 - 500 +# Kelvins: 6500K - 2000K +# +# @subscribe input_boolean.kitchen_lights_override +# @subscribe input_boolean.night_mode +# @subscribe input_boolean.scene_mode +# +# @link https://community.home-assistant.io/t/lifx-circadian-rhythm-time-of-day-automation/23091 +# @link https://sigmaluminous.com/the-circadian-rhythm-and-color-temperature/ +# +- id: cct_limitlessled + alias: CCT LimitlessLED + trigger: + # Every five minutes. + - platform: time + minutes: /5 + seconds: 00 + + # When an item which was turned off or disconnected comes back online. + - platform: state + entity_id: + - light.countertop + - light.island + - light.microwave + - light.sink + to: 'on' + + # When scenes are disabled. + - platform: state + entity_id: input_boolean.scene_mode + to: 'off' + + # When kitchen lights override has been set a while ago already. + - platform: state + entity_id: input_boolean.kitchen_lights_override + to: 'on' + for: + minutes: 20 + + condition: + # If at least one light is on. + - condition: state + entity_id: group.kitchen_lights + state: 'on' + + # If no scenes are enabled. + - condition: state + entity_id: input_boolean.scene_mode + state: 'off' + + # It's not during the night mode. + - condition: state + entity_id: input_boolean.night_mode + state: 'off' + + action: + # Set light colour and brightness. + - service: light.turn_on + data_template: + entity_id: >- + {% set entities = '' %} + {% if is_state('light.countertop', 'on') %} + {% set entities = entities + 'light.countertop ' %} + {% endif %} + {% if is_state('light.island', 'on') %} + {% set entities = entities + 'light.island ' %} + {% endif %} + {% if is_state('light.microwave', 'on') %} + {% set entities = entities + 'light.microwave ' %} + {% endif %} + {% if is_state('light.sink', 'on') %} + {% set entities = entities + 'light.sink ' %} + {% endif %} + + {{ entities | trim | replace(' ',',') }} + color_temp: >- + {% set schedule = { + '00': 3000, + '01': 2750, + '02': 2500, + '03': 2000, + '04': 2500, + '05': 2750, + + '06': 3000, + '07': 3500, + '08': 4000, + '09': 4500, + '10': 5000, + '11': 5500, + + '12': 6000, + '13': 6000, + '14': 6000, + '15': 6000, + '16': 6000, + '17': 5500, + + '18': 5000, + '19': 4500, + '20': 4000, + '21': 3500, + '22': 3500, + '23': 3500, + } %} + {% set hour = now().hour %} + {% set next = hour + 1%} + {% if next > 23 %} + {% set next = 0 %} + {% endif %} + {% set hour = '%02d' | format(hour) %} + {% set next = '%02d' | format(next) %} + + {% set current = schedule[hour] %} + {% set target = schedule[next] %} + {% set color_temp = current %} + + {% if current != target %} + {% set delta = target - current %} + {% set seconds = now().second + now().minute * 60 %} + {% set diff = (seconds / 3600 * delta) | round(0) %} + {% set color_temp = current + diff %} + {% endif %} + + {% set color = (1000000 / color_temp) | round(0) %} + + {{ color }} + brightness: >- + {% set schedule = { + '00': 50, + '01': 50, + '02': 45, + '03': 40, + '04': 35, + '05': 40, + + '06': 45, + '07': 50, + '08': 60, + '09': 70, + '10': 80, + '11': 90, + + '12': 100, + '13': 100, + '14': 100, + '15': 100, + '16': 95, + '17': 85, + + '18': 80, + '19': 75, + '20': 70, + '21': 65, + '22': 60, + '23': 55, + } %} + {% set hour = now().hour %} + {% set next = hour + 1%} + {% if next > 23 %} + {% set next = 0 %} + {% endif %} + {% set hour = '%02d' | format(hour) %} + {% set next = '%02d' | format(next) %} + + {% set current = schedule[hour] %} + {% set target = schedule[next] %} + {% set brightness_pct = current %} + + {% if current != target %} + {% set delta = target - current %} + {% set seconds = now().second + now().minute * 60 %} + {% set diff = (seconds / 3600 * delta) | round(0) %} + {% set brightness_pct = current + diff %} + {% endif %} + + {% set brightness = (brightness_pct / 100 * 255) | round(0) %} + + {{ brightness }} diff --git a/automations/ceiling_default.yaml b/automations/ceiling_default.yaml deleted file mode 100644 index edfd8a5..0000000 --- a/automations/ceiling_default.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# -# Return the ceiling wash lights to the default scheduled effect. -# -# By removing the manual override, the ceiling lights will automatically fall -# back to the regularly schedule effect. -# -# @subscribe variable.ceiling_effect -# -# @see /automations/ceiling_schedule.yaml -# @see /scenes/lifx_cloud.yaml -# -- id: ceiling_default - alias: Ceiling DEFAULT - trigger: - # If the default effect is selected. - - platform: state - entity_id: input_select.ceiling_effect - to: Auto - - action: - # Remove the effect override. - - service: input_boolean.turn_off - entity_id: input_boolean.ceiling_effect_override diff --git a/automations/ceiling_effect.yaml b/automations/ceiling_effect.yaml index e60c2cd..8afd6d3 100644 --- a/automations/ceiling_effect.yaml +++ b/automations/ceiling_effect.yaml @@ -1,5 +1,5 @@ # -# Change ceiling wash lights based on Lifx Cloud scenes. +# Change ceiling wash lights based on Lifx Cloud scenes # # The LIFX strips have effects programmed with the LIFX mobile and stored on # their servers. Each effect mentions which device will receive which color diff --git a/automations/ceiling_off.yaml b/automations/ceiling_off.yaml index 682e235..4c0d9c0 100644 --- a/automations/ceiling_off.yaml +++ b/automations/ceiling_off.yaml @@ -1,5 +1,8 @@ # -# Turn off ceiling wash lights. +# Turn off ceiling wash lights +# +# @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode # - id: ceiling_off alias: Ceiling OFF @@ -19,5 +22,5 @@ - service: homeassistant.turn_off data: entity_id: - - group.ceiling + - group.ceiling_lights transition: 10 diff --git a/automations/ceiling_on.yaml b/automations/ceiling_on.yaml index eccbfbd..edb2450 100644 --- a/automations/ceiling_on.yaml +++ b/automations/ceiling_on.yaml @@ -1,5 +1,8 @@ # -# Turn on ceiling wash lights. +# Turn on ceiling wash lights +# +# @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode # - id: ceiling_on alias: Ceiling ON @@ -30,5 +33,5 @@ - service: homeassistant.turn_on data: entity_id: - - group.ceiling + - group.ceiling_lights transition: 5 diff --git a/automations/ceiling_schedule.yaml b/automations/ceiling_schedule.yaml index 9063579..19adb47 100644 --- a/automations/ceiling_schedule.yaml +++ b/automations/ceiling_schedule.yaml @@ -1,11 +1,14 @@ # -# Schedule ceiling wash lights based on Lifx Cloud scenes. +# Schedule ceiling wash lights based on Lifx Cloud scenes # # Unless an effect is manually selected, this scheduler will do its thing. # -# @publish variable.ceiling_effect -# @subscribe input_boolean.ceiling_effect_override +# @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode # @subscribe input_boolean.scene_mode +# @subscribe input_select.ceiling_effect +# +# @publish variable.ceiling_effect # # @see /automations/ceiling_effect.yaml # @@ -36,10 +39,10 @@ entity_id: input_boolean.scene_mode to: 'off' - # When ceiling wash light effect override is being released. + # When the selected effect is switched to default. - platform: state - entity_id: input_boolean.ceiling_effect_override - to: 'off' + entity_id: input_select.ceiling_effect + to: 'Auto' condition: # If automation was not trigered lately (debounce). @@ -52,25 +55,25 @@ # If ceiling wash lights are on. - condition: state - entity_id: group.ceiling + entity_id: group.ceiling_lights state: 'on' - # If no effect overrides are in place. + # If the selected effect is the default. - condition: state - entity_id: input_boolean.ceiling_effect_override - state: 'off' + entity_id: input_select.ceiling_effect + state: 'Auto' # If no scenes are enabled. - condition: state entity_id: input_boolean.scene_mode state: 'off' - # Not during the night mode. + # It it's not during the night mode. - condition: state entity_id: input_boolean.night_mode state: 'off' - # Not during the nap mode. + # It it's not during the nap mode. - condition: state entity_id: input_boolean.nap_mode state: 'off' diff --git a/automations/ceiling_select.yaml b/automations/ceiling_select.yaml index e06f83f..5aab661 100644 --- a/automations/ceiling_select.yaml +++ b/automations/ceiling_select.yaml @@ -1,5 +1,7 @@ # -# Manually select a LIFX cloud effect for the ceiling wash lights. +# Manually select a LIFX cloud effect for the ceiling wash lights +# +# @subscribe input_select.ceiling_effect # # @publish variable.ceiling_effect # @@ -8,20 +10,25 @@ - id: ceiling_select alias: Ceiling SELECT trigger: - # An effect has been selected. + # When an effect has been selected. - platform: state entity_id: input_select.ceiling_effect + # When an item which was off comes back online. + - platform: state + entity_id: + - light.bedroom + - light.lounge + - light.middle + to: 'on' + condition: # If an actual effect is selected, not the default. - condition: template - value_template: "{% if not is_state('input_select.ceiling_effect', 'Auto') %}true{% endif %}" + value_template: >- + {{ not is_state('input_select.ceiling_effect', 'Auto') }} action: - # Prevent the ceiling scheduler from replacing the selected effect. - - service: input_boolean.turn_on - entity_id: input_boolean.ceiling_effect_override - # Update the ceiling effect variables. - service: variable.set_variable data: diff --git a/automations/check_doors.yaml b/automations/check_doors.yaml deleted file mode 100644 index 8268831..0000000 --- a/automations/check_doors.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# -# Warns someone if a door was left open for too long -# -# Todo: Add condition that no one has been detected at home. -# -# @subscribe input_boolean.doors_open -# -- id: check_door_left_open - alias: Check door left open - trigger: - # A door has been left open for a while. - - platform: state - entity_id: input_boolean.doors_open - to: 'on' - for: - minutes: 10 - - action: - # Warn someone to take action. - - service: notify.group - data: - title: "Home security issue" - message: "A door has been left open for too long." diff --git a/automations/check_humidity_high.yaml b/automations/check_humidity_high.yaml deleted file mode 100644 index 01c1d41..0000000 --- a/automations/check_humidity_high.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# -# Check if humidity is too high -# -# Only verify if doors and windows are closed. -# -# @subscribe input_boolean.doors_open -# @subscribe input_boolean.windows_open -# -# @see /automations/check_mold.yaml -# -- id: check_humidity_high - alias: Check humidity HIGH - trigger: - # Comfort level should be between 35% and 55%. - - platform: numeric_state - entity_id: sensor.average_humidity - above: 55 - below: 61 - - condition: - # Doors are closed. - - condition: state - entity_id: input_boolean.doors_open - state: 'off' - for: - minutes: 60 - - # Windows are closed. - - condition: state - entity_id: input_boolean.windows_open - state: 'off' - for: - minutes: 60 - - action: - # Warn someone to take action (like empty the dehumidifier's collection - # bucket). - - service: notify.group - data: - title: "Home humidity is too high" - message: | - {{ states('sensor.average_humidity') }}% is excessive. - Check the dehumidifier. - - # Pin a warning message in the frontend. - - service: persistent_notification.create - data: - notification_id: humidity - title: "Humidity is too high" - message: >- - {{ states('sensor.average_humidity') }}% is excessive.\n - Check the dehumidifier. diff --git a/automations/check_humidity_low.yaml b/automations/check_humidity_low.yaml deleted file mode 100644 index 0e49ff1..0000000 --- a/automations/check_humidity_low.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# -# Check if humidity is too low -# -# Only verify if doors and windows are closed. -# -# @subscribe input_boolean.doors_open -# @subscribe input_boolean.windows_open -# -- id: check_humidity_low - alias: Check humidity LOW - trigger: - # Comfort level should be between 35% and 55%. - - platform: numeric_state - entity_id: sensor.average_humidity - below: 35 - - condition: - # Doors are closed. - - condition: state - entity_id: input_boolean.doors_open - state: 'off' - for: - minutes: 60 - - # Windows are closed. - - condition: state - entity_id: input_boolean.windows_open - state: 'off' - for: - minutes: 60 - - action: - # Warn someone to take action (like refill the humidifier). - - service: notify.group - data: - title: "Home humidity is too low" - message: | - {{ states('sensor.average_humidity') }}% is too dry. - Check the humidifier. - - # Pin a warning message in the frontend. - - service: persistent_notification.create - data: - notification_id: humidity - title: "Humidity is too low" - message: >- - {{ states('sensor.average_humidity') }}% is too dry.\n - Check the humidifier. diff --git a/automations/check_mold.yaml b/automations/check_mold.yaml deleted file mode 100644 index c19b374..0000000 --- a/automations/check_mold.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# -# Warn someone if humidity levels may lead to mold issues -# -# Only triggers if windows and doors are open, because we're not responsible -# for what's happening outside. -# -# @subscribe input_boolean.doors_open -# @subscribe input_boolean.windows_open -# -# @see /automations/check_humidity.yaml -# -- id: check_mold_conditions - alias: Check mold conditions - trigger: - # Mold grows above 55% relative humidity, and thrives above 70%. - - platform: numeric_state - entity_id: sensor.average_humidity - above: 60 - - condition: - # Doors have been closed for a while. - - condition: state - entity_id: input_boolean.doors_open - state: 'off' - for: - minutes: 60 - - # Windows have been closed for a while. - - condition: state - entity_id: input_boolean.doors_open - state: 'off' - for: - minutes: 60 - - action: - # Warn someone to take action (like empty the dehumidifier's collection - # bucket). - - service: notify.group - data: - title: "Home humidity is way too high" - message: | - {{ states('sensor.average_humidity') }}% = Risk of mold! - Check the dehumidifier. - - # Pin a warning message in the frontend. - - service: persistent_notification.create - data: - notification_id: mold - title: "Risk of mold!" - message: >- - Humidity is way too high: {{ states('sensor.average_humidity') }}%\n - Check the dehumidifier. diff --git a/automations/daily_greeting.yaml b/automations/daily_greeting.yaml new file mode 100644 index 0000000..0085201 --- /dev/null +++ b/automations/daily_greeting.yaml @@ -0,0 +1,85 @@ +# +# Greet the day with a daily briefing +# +# @subscribe input_boolean.night_mode +# @subscribe input_boolean.nap_mode +# +- id: daily_greeting + alias: Daily greeting + trigger: + # When night mode is disabled. + - platform: state + entity_id: input_boolean.night_mode + to: 'off' + + condition: + # If nap mode is disabled. + - condition: state + entity_id: input_boolean.nap_mode + state: 'off' + + action: + # Sound the day. + - service: notify.sound + data: + message: "doorbell" + data: + method: "alarm" + - delay: + seconds: 2 + + # Greet the day. + - service: notify.speech + data_template: + message: >- + {% set temperature = states('sensor.outside_temperature') | int %} + {% set apparent = states('sensor.dark_sky_apparent_temperature') | round(0) %} + {% set minutely = states('sensor.dark_sky_minutely_summary') | lower %} + {% set hourly = states('sensor.dark_sky_hourly_summary') | lower %} + {% set windspeed = (states('sensor.dark_sky_wind_speed')|float * 3600 / 1000) | round(1) %} + {% set hour = states('sensor.time').split(':')[0] | int %} + + {%- if hour >= 4 and hour < 12 -%} + Good morning beautiful people! + {%- elif hour >= 12 and hour < 18 -%} + Good afternoon productive people! + {%- elif hour >= 18 and hour < 22 -%} + Good evening friendly people! + {%- else -%} + Good night sleepy people! + {% endif %} + + We are {{ states('sensor.date_long') }} and it is {{ states('sensor.time_long') }}. + + Outside temperature is {{ temperature }}˚ {% + if apparent != temperature -%} + but feels like {{ apparent }} + {%- endif -%} + . + + {% if minutely != 'unknown' -%} + It will be {{ minutely.rstrip('.') }} {% + if hourly != 'unknown' -%} + and will be {{ hourly }} + {% endif %} + {% else -%} + It is currently {{ states('sensor.dark_sky_summary') -}} + {%- if hourly != 'unknown' %} and will be {{ hourly }} + {%- else -%} + . + {%- endif %} + {% endif %} + + {%- if 40 <= windspeed -%} + It is windy. {% + endif -%} + A {{ states('sensor.wind_scale_friendly') | lower }} is blowing from the {{ states('sensor.wind_bearing_cardinal_friendly') }}. + + Air quality is {{ states('sensor.aqi_friendly') | lower }} {% + if is_state('sun.sun', 'above_horizon') -%} + , UV index is {{ states('sensor.uv_friendly') | lower }} + {%- endif %} and the sun {{ states('sensor.sun_state_friendly') }}. + + Have a nice day! + + {{ states('sensor.good_vibes') }} diff --git a/automations/dehumidifier_off.yaml b/automations/dehumidifier_off.yaml index 709aefb..249593e 100644 --- a/automations/dehumidifier_off.yaml +++ b/automations/dehumidifier_off.yaml @@ -8,33 +8,33 @@ - id: dehumidifier_off alias: Dehumidifier OFF trigger: - # Humidity is getting too low. + # When humidity is getting too low. - platform: numeric_state entity_id: sensor.average_humidity below: 35 - # Dehumidifier has been running for a while. + # When dehumidifier has been running for a while. - platform: state entity_id: switch.dehumidifier to: 'on' for: hours: 2 - # Outside doors have been open for a while. + # When outside doors have been open for a while. - platform: state entity_id: input_boolean.doors_open to: 'on' for: minutes: 10 - # Windows have been open for a while. + # When windows have been open for a while. - platform: state entity_id: input_boolean.windows_open to: 'on' for: minutes: 2 - # It's quiet time. + # When it's quiet time. - platform: state entity_id: input_boolean.quiet_mode to: 'on' diff --git a/automations/dehumidifier_on.yaml b/automations/dehumidifier_on.yaml index 37d5feb..d55d279 100644 --- a/automations/dehumidifier_on.yaml +++ b/automations/dehumidifier_on.yaml @@ -11,36 +11,42 @@ - id: dehumidifier_on alias: Dehumidifier ON trigger: - # Humidity is getting too high. + # When humidity is getting too high. - platform: numeric_state entity_id: sensor.average_humidity above: 50 + for: + hours: 1 condition: - # It's the afternoon. + # If it's during the afternoon. - condition: time after: '12:00:00' before: '18:00:00' - # It's not quiet time. + # If it's not quiet time. - condition: state entity_id: input_boolean.quiet_mode state: 'off' - # Dehumidifier isn't already running. + # If dehumidifier isn't already running. - condition: state entity_id: switch.dehumidifier state: 'off' - # Doors are closed. + # If doors have been closed for a while. - condition: state entity_id: input_boolean.doors_open state: 'off' + for: + minutes: 5 - # Windows are closed. + # If windows have been closed for a while. - condition: state entity_id: input_boolean.windows_open state: 'off' + for: + minutes: 5 action: # Turn dehumidifier on. diff --git a/automations/doors_notify.yaml b/automations/doors_notify.yaml new file mode 100644 index 0000000..e58705a --- /dev/null +++ b/automations/doors_notify.yaml @@ -0,0 +1,40 @@ +# +# Warns someone if a door was left open for too long +# +# Todo: Add condition that no one has been detected at home. +# +# @subscribe input_boolean.doors_open +# +- id: doors_notify + alias: Doors NOTIFY + trigger: + # When a door has been left open for a while. + - platform: state + entity_id: input_boolean.doors_open + to: 'on' + for: + minutes: 10 + + action: + # Warn someone by text to take action. + - service: notify.text + data: + title: "Home security issue" + message: "A door has been left open for too long." + + # # Play a warning sound. + # - condition: state + # entity_id: input_binary.quiet_mode + # state: 'off' + # - service: notify.sound + # data: + # message: "alarm" + # data: + # method: "alarm" + + # # Play a warning message. + # - delay: + # seconds: 2 + # - service: notify.speech + # data: + # message: "Attention: A door has been left open for too long." diff --git a/automations/doors_verify.yaml b/automations/doors_verify.yaml new file mode 100644 index 0000000..ca5a959 --- /dev/null +++ b/automations/doors_verify.yaml @@ -0,0 +1,27 @@ +# +# Verify the state of all external doors +# +# Marks the perimeter as breached when any door is open, and safe when all are +# closed. +# +# @subscribe binary_sensor.front_door_sensor +# +# @publish input_boolean.doors_open +# +- id: doors_verify + alias: Doors VERIFY + trigger: + # When an external door sensor has changed. + - platform: state + entity_id: + - binary_sensor.front_door_sensor + + action: + # Toggle doors status. + - service_template: > + {% if is_state('binary_sensor.front_door_sensor', 'on') %} + input_boolean.turn_on + {% else %} + input_boolean.turn_off + {% endif %} + entity_id: input_boolean.doors_open diff --git a/automations/front_door_closed.yaml b/automations/front_door_closed.yaml deleted file mode 100644 index d7aadca..0000000 --- a/automations/front_door_closed.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# -# Warn whenever the front door is closing -# -# Useful to indicate to an otherwise oblivious showering partner that the front -# door has closed. -# -# Todo: map door sensor state values to binary values. -# -# @see /lights/lifx.yaml -# -- id: front_door_closed - alias: Front door CLOSED - trigger: - # The front door sensor senses closure. - - platform: state - entity_id: sensor.aeotec_zw120_door_window_sensor_gen5_access_control - from: '22' - to: '23' - - action: - # Flash the shower light, in case one didn't hear the door closing. - - service: light.lifx_effect_pulse - data: - entity_id: - - light.shower - mode: blink - color_name: purple - brightness: 120 - period: 1 - cycles: 1 diff --git a/automations/front_door_notify.yaml b/automations/front_door_notify.yaml new file mode 100644 index 0000000..65d133a --- /dev/null +++ b/automations/front_door_notify.yaml @@ -0,0 +1,51 @@ +# +# Warn whenever the front door is opening or closing +# +# Useful to indicate to an otherwise oblivious showering partner that someone +# likely just came in or left the premises. +# +# @subscribe binary_sensor.front_door_sensor +# +# @see /lights/lifx.yaml +# +- id: front_door_notify + alias: Front door NOTIFY + trigger: + # When the front door sensor senses openness or closure. + - platform: state + entity_id: binary_sensor.front_door_sensor + + action: + # Flash some smart lights, in case one didn't hear a door opening/closing. + - service: light.lifx_effect_pulse + data: + entity_id: group.lifx_lights + brightness: 120 + period: 1 + cycles: 1 + data_template: + mode: >- + {% if is_state('binary_sensor.front_door_sensor', 'on') %} + breathe + {% else %} + blink + {% endif %} + color_name: >- + {% if is_state('binary_sensor.front_door_sensor', 'on') %} + cyan + {% else %} + purple + {% endif %} + + # Play a welcoming sound. + - condition: state + entity_id: binary_sensor.front_door_sensor + state: 'on' + - condition: state + entity_id: input_boolean.quiet_mode + state: 'off' + - service: notify.sound + data: + message: "chime" + data: + method: "alarm" diff --git a/automations/front_door_opened.yaml b/automations/front_door_opened.yaml deleted file mode 100644 index 66c98fe..0000000 --- a/automations/front_door_opened.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# -# Warn whenever the front door is opening -# -# Useful to indicate to an otherwise oblivious showering partner that the front -# door has opened. -# -# Todo: map door sensor state values to binary values. -# -# @see /lights/lifx.yaml -# -- id: front_door_opened - alias: Front door OPENED - trigger: - # The front door sensor senses openness. - - platform: state - entity_id: sensor.aeotec_zw120_door_window_sensor_gen5_access_control - from: '23' - to: '22' - - action: - # Flash the shower light, in case one didn't hear the door opening. - - service: light.lifx_effect_pulse - data: - entity_id: - - light.shower - mode: breathe - color_name: cyan - brightness: 120 - period: 1 - cycles: 1 diff --git a/automations/humidity_notify.yaml b/automations/humidity_notify.yaml new file mode 100644 index 0000000..b62c27c --- /dev/null +++ b/automations/humidity_notify.yaml @@ -0,0 +1,122 @@ +# +# Check if humidity is too high +# +# Comfort level should be between 35% and 55%. +# Mold grows above 55% relative humidity, and thrives above 70%. +# Only verify if doors and windows are closed. +# +# @subscribe input_boolean.doors_open +# @subscribe input_boolean.windows_open +# +# @see /automations/check_mold.yaml +# +- id: humidity_notify + alias: Humidity NOTIFY + trigger: + # When humidity is getting too high. + - platform: numeric_state + entity_id: sensor.average_humidity + above: 55 + + # When humidity is getting too low. + - platform: numeric_state + entity_id: sensor.average_humidity + below: 35 + + condition: + # If doors have been closed for a while. + - condition: state + entity_id: input_boolean.doors_open + state: 'off' + for: + minutes: 60 + + # If windows have been closed for a while. + - condition: state + entity_id: input_boolean.windows_open + state: 'off' + for: + minutes: 60 + + action: + # Pin a warning message in the frontend. + - service: persistent_notification.create + data: + notification_id: humidity + data_template: + title: >- + {% set humidity = states('sensor.average_humidity') | int %} + {% if (humidity > 65) %} + Home humidity is WAY too high + {% elif (humidity >= 55) %} + Home humidity is too high + {% else %} + Home humidity is too low + {% endif %} + message: >- + {% set humidity = states('sensor.average_humidity') | int %} + {% if (humidity > 65) %} + {{ states('sensor.average_humidity') }}% = Risk of mold!
+ Check the dehumidifier NOW! + {% elif (humidity >= 55) %} + {{ states('sensor.average_humidity') }}% is excessive.
+ Check the dehumidifier. + {% else %} + {{ states('sensor.average_humidity') }}% is too dry.
+ Check the humidifier. + {% endif %} + + # Warn someone by text to take action. + - service: notify.text + data_template: + title: >- + {% set humidity = states('sensor.average_humidity') | int %} + {% if (humidity > 65) %} + Home humidity is WAY too high + {% elif (humidity >= 55) %} + Home humidity is too high + {% else %} + Home humidity is too low + {% endif %} + message: | + {% set humidity = states('sensor.average_humidity') | int %} + {% if (humidity > 65) %} + {{ states('sensor.average_humidity') }}% = Risk of mold! + Check the dehumidifier NOW! + {% elif (humidity >= 55) %} + {{ states('sensor.average_humidity') }}% is excessive. + Check the dehumidifier. + {% else %} + {{ states('sensor.average_humidity') }}% is too dry. + Check the humidifier. + {% endif %} + + # Play a warning sound and message. + - condition: state + entity_id: input_boolean.quiet_mode + state: 'off' + - service: notify.sound + data: + message: "alarm" + data: + method: "alarm" + - delay: + seconds: 2 + - service: notify.speech + data_template: + message: >- + {% set humidity = states('sensor.average_humidity') | int %} + {% if (humidity > 65) %} + Humidity is way too high. + Currently at {{ states('sensor.average_humidity') }}%. + There is a risk of mold! + Check the dehumidifier NOW! + {% elif (humidity >= 55) %} + Humidity is too high. + Currently at {{ states('sensor.average_humidity') }}% which is excessive. + Check the dehumidifier. + {% else %} + Humidity is too low. + Currently at {{ states('sensor.average_humidity') }}% which is too dry. + Check the humidifier. + {% endif %} diff --git a/automations/kiosk_auto.yaml b/automations/kiosk_auto.yaml new file mode 100644 index 0000000..59108a5 --- /dev/null +++ b/automations/kiosk_auto.yaml @@ -0,0 +1,43 @@ +# +# Toggle kiosk display +# +# @subscribe input_boolean.night_mode +# +- id: kiosk_auto + alias: Kiosk AUTO + trigger: + # When night mode is changed. + - platform: state + entity_id: input_boolean.night_mode + + action: + # Dim/brighten display. + - service: shell_command.kiosk_brightness + data: + host: !secret fully_kiosk_host + port: !secret fully_kiosk_port + password: !secret fully_kiosk_password + data_template: + value: >- + {% if is_state('input_boolean.night_mode', 'off') %} + 255 + {% else %} + 0 + {% endif %} + + # Keep the screen on for a few more seconds when we're turning it off. + - delay: >- + {% if is_state('input_boolean.night_mode', 'off') %} + 00:00:00 + {% else %} + 00:00:05 + {% endif %} + + # Toggle display. + - service_template: >- + {% if is_state('input_boolean.night_mode', 'off') %} + homeassistant.turn_on + {% else %} + homeassistant.turn_off + {% endif %} + entity_id: display.kiosk diff --git a/automations/kiosk_low.yaml b/automations/kiosk_low.yaml new file mode 100644 index 0000000..52efda3 --- /dev/null +++ b/automations/kiosk_low.yaml @@ -0,0 +1,26 @@ +# +# Toggle kiosk display brightness +# +# @subscribe input_boolean.low_mode +# +- id: kiosk_low_power + alias: Kiosk LOW POWER + trigger: + # When low-power mode is changed. + - platform: state + entity_id: input_boolean.low_mode + + action: + # Dim/brighten display. + - service: shell_command.kiosk_brightness + data: + host: !secret fully_kiosk_host + port: !secret fully_kiosk_port + password: !secret fully_kiosk_password + data_template: + value: >- + {% if is_state('input_boolean.low_mode', 'off') %} + 255 + {% else %} + 0 + {% endif %} diff --git a/automations/kitchen_lights_full.yaml b/automations/kitchen_lights_full.yaml new file mode 100644 index 0000000..8c0bb15 --- /dev/null +++ b/automations/kitchen_lights_full.yaml @@ -0,0 +1,41 @@ +# +# Turn full on kitchen lights +# +# Set all kitchen lights to maximum brightness when Flick button is held. +# +# @publish input_boolean.kitchen_lights_override +# +# @see /automations/cct_limitlessled.yaml +# +- id: kitchen_lights_full + alias: Kitchen lights FULL + trigger: + # When Minimote button 3 is held. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 6 # 6 = button #3 held. + + # When kitchen Flic button is held. + - platform: event + event_type: flic_click + event_data: + button_name: flic_80e4da72e890 + click_type: hold + + action: + # Turn on all lights. + - service: homeassistant.turn_on + data: + entity_id: + - group.kitchen_lights + brightness_pct: 100 + + # Force kitchen lights override. + - service: homeassistant.turn_off + data: + entity_id: input_boolean.kitchen_lights_override + - service: homeassistant.turn_on + data: + entity_id: input_boolean.kitchen_lights_override diff --git a/automations/kitchen_lights_init.yaml b/automations/kitchen_lights_init.yaml new file mode 100644 index 0000000..3e952a6 --- /dev/null +++ b/automations/kitchen_lights_init.yaml @@ -0,0 +1,26 @@ +# +# Set kitchen lights to a known state. +# +# LimitlessLED lights do not provide state information, so we force it depending +# on the current conditions. +# +- id: kitchen_lights_init + alias: Kitchen lights INIT + trigger: + # When Home Assistant starts. + - platform: homeassistant + event: start + + action: + # Toggle lights. + - service_template: > + {% if is_state('input_boolean.night_mode', 'off') + and is_state('input_boolean.nap_mode', 'off') + %} + homeassistant.turn_on + {% else %} + homeassistant.turn_off + {% endif %} + data: + entity_id: + - group.kitchen_lights diff --git a/automations/kitchen_lights_off.yaml b/automations/kitchen_lights_off.yaml new file mode 100644 index 0000000..8fb1558 --- /dev/null +++ b/automations/kitchen_lights_off.yaml @@ -0,0 +1,27 @@ +# +# Turn off kitchen lights +# +# Turn off all kitchen lights when Flick button is single clicked. +# +- id: kitchen_lights_off + alias: Kitchen lights OFF + trigger: + # When kitchen Flic button is pressed once. + - platform: event + event_type: flic_click + event_data: + button_name: flic_80e4da72e890 + click_type: single + + condition: + # If any kitchen lights are on. + - condition: state + entity_id: group.kitchen_lights + state: 'on' + + action: + # Turn off all lights. + - service: homeassistant.turn_off + data: + entity_id: + - group.kitchen_lights diff --git a/automations/kitchen_lights_on.yaml b/automations/kitchen_lights_on.yaml new file mode 100644 index 0000000..21102af --- /dev/null +++ b/automations/kitchen_lights_on.yaml @@ -0,0 +1,27 @@ +# +# Turn on kitchen lights +# +# Turn on all kitchen lights when Flick button is single clicked. +# +- id: kitchen_lights_on + alias: Kitchen lights ON + trigger: + # When kitchen Flic button is pressed once. + - platform: event + event_type: flic_click + event_data: + button_name: flic_80e4da72e890 + click_type: single + + condition: + # If all kitchen links are off. + - condition: state + entity_id: group.kitchen_lights + state: 'off' + + action: + # Turn on all lights. + - service: homeassistant.turn_on + data: + entity_id: + - group.kitchen_lights diff --git a/automations/kitchen_lights_toggle.yaml b/automations/kitchen_lights_toggle.yaml new file mode 100644 index 0000000..1b68914 --- /dev/null +++ b/automations/kitchen_lights_toggle.yaml @@ -0,0 +1,41 @@ +# +# Toggle kitchen lights +# +# Toggles between 2 and 4 lights when Flick button is double clicked. +# +- id: kitchen_lights_toggle + alias: Kitchen lights TOGGLE + trigger: + # When Minimote button 3 is clicked. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 5 # 5 = button #3 clicked. + + # When kitchen Flic button is double-clicked. + - platform: event + event_type: flic_click + event_data: + button_name: flic_80e4da72e890 + click_type: double + + action: + # Toggle extra lights. + - service_template: > + {% if is_state('light.countertop', 'on') or is_state('light.sink', 'off') %} + homeassistant.turn_off + {% else %} + homeassistant.turn_on + {% endif %} + data: + entity_id: + - light.countertop + - light.island + + # Turn on essential lights. + - service: homeassistant.turn_on + data: + entity_id: + - light.sink + - light.microwave diff --git a/automations/kitchen_low.yaml b/automations/kitchen_low.yaml new file mode 100644 index 0000000..a97ef47 --- /dev/null +++ b/automations/kitchen_low.yaml @@ -0,0 +1,27 @@ +# +# Set kitchen to low-power mode +# +# @subscribe input_boolean.low_mode +# +- id: kitchen_low_power + alias: Kitchen LOW POWER + trigger: + # When low-power mode is enabled. + - platform: state + entity_id: input_boolean.low_mode + to: 'on' + + action: + # Turn on some lights. + - service: homeassistant.turn_on + data: + entity_id: + - light.microwave + - light.sink + + # Turn off some lights. + - service: homeassistant.turn_off + data: + entity_id: + - light.countertop + - light.island diff --git a/automations/kitchen_off.yaml b/automations/kitchen_off.yaml new file mode 100644 index 0000000..9452b15 --- /dev/null +++ b/automations/kitchen_off.yaml @@ -0,0 +1,19 @@ +# +# Turn off kitchen +# +# @subscribe input_boolean.night_mode +# +- id: kitchen_off + alias: Kitchen OFF + trigger: + # When night mode is enabled. + - platform: state + entity_id: input_boolean.night_mode + to: 'on' + + action: + # Turn off all lights. + - service: homeassistant.turn_off + data: + entity_id: + - group.kitchen_lights diff --git a/automations/kitchen_on.yaml b/automations/kitchen_on.yaml new file mode 100644 index 0000000..df53fda --- /dev/null +++ b/automations/kitchen_on.yaml @@ -0,0 +1,36 @@ +# +# Turn on kitchen +# +# @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode +# +- id: kitchen_on + alias: Kitchen ON + trigger: + # When nap mode is disabled. + - platform: state + entity_id: input_boolean.nap_mode + to: 'off' + + # When night mode is disabled. + - platform: state + entity_id: input_boolean.night_mode + to: 'off' + + condition: + # If nap mode is disabled. + - condition: state + entity_id: input_boolean.nap_mode + state: 'off' + + # If night mode is disabled + - condition: state + entity_id: input_boolean.night_mode + state: 'off' + + action: + # Turn on all lights. + - service: homeassistant.turn_on + data: + entity_id: + - group.kitchen_lights diff --git a/automations/lightpack_effect.yaml b/automations/lightpack_effect.yaml new file mode 100644 index 0000000..8acdf30 --- /dev/null +++ b/automations/lightpack_effect.yaml @@ -0,0 +1,50 @@ +# +# Change lightpack based on its programmed profiles +# +# The Lightpack is controlled by the Prismatik softwage, which allows for +# different profiles to be created and loaded at will. They have unique names, +# but let's use a translation map here to reduce name binding between Home +# Assistant and daily HTPC usage. +# +# @subscribe variable.lightpack_effect +# +# @see /automations/lightpack_select.yaml +# @see /custom_components/light/lightpack.yaml +# +# @link https://github.com/psieg/Lightpack +# +- id: lightpack_effect + alias: Lightpack EFFECT + trigger: + # When an effect is changed. + - platform: state + entity_id: variable.lightpack_effect + + action: + # Turn on the Lightpack so that the switch represents the actual state, + # since sending the effect in the next step will turn on the light anyway. + - service: homeassistant.turn_on + data: + entity_id: + - light.lightpack + + # Send the effect's real name to the Lightpack API. + - service: light.set_profile + data: + entity_id: + - light.lightpack + data_template: + profile: >- + {% set effects = { + 'Default': 'Ambilight', + 'Daylight': 'Daylight', + 'Gaming': 'Gaming', + 'Movie': 'Ambilight', + 'Romantic': 'Romantic', + 'Party': 'SoundVisualizer', + } %} + {% set selected = states('variable.lightpack_effect') %} + + {% if effects[selected] %} + {{ effects[selected] }} + {% endif %} diff --git a/automations/lightpack_select.yaml b/automations/lightpack_select.yaml new file mode 100644 index 0000000..20ff2f9 --- /dev/null +++ b/automations/lightpack_select.yaml @@ -0,0 +1,29 @@ +# +# Manually select a Lightpack effect for the TV bias light +# +# @subscribe input_select.lightpack_effect +# +# @publish variable.lightpack_effect +# +# @see /automations/lightpack_effect.yaml +# +- id: lightpack_select + alias: Lightpack SELECT + trigger: + # When an effect has been selected. + - platform: state + entity_id: input_select.lightpack_effect + + # When an item which was off comes back online. + - platform: state + entity_id: + - light.lightpack + to: 'on' + + action: + # Update the Lightpack effect variables. + - service: variable.set_variable + data: + variable: lightpack_effect + value_template: >- + {{ states('input_select.lightpack_effect') }} diff --git a/automations/low_mode_start.yaml b/automations/low_mode_start.yaml index be754a0..880c7b2 100644 --- a/automations/low_mode_start.yaml +++ b/automations/low_mode_start.yaml @@ -14,7 +14,7 @@ to: 'on' condition: - # If night mode is not currently enabled. + # If it's not night mode. - condition: state entity_id: input_boolean.night_mode state: 'off' diff --git a/automations/media_player_resume.yaml b/automations/media_player_resume.yaml deleted file mode 100644 index 1e72a4b..0000000 --- a/automations/media_player_resume.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# -# Media player plays content -# -# @subscribe input_boolean.nap_mode -# -# @publish input_boolean.scene_mode -# @publish variable.aurora_brightness -# @publish variable.aurora_effect -# @publish variable.ceiling_effect -# -- id: media_player_resume - alias: Media player RESUME - trigger: - # Kodi resumes playback. - - platform: state - entity_id: media_player.kodi - to: 'playing' - - condition: - # Sun has set. - - condition: state - entity_id: sun.sun - state: 'below_horizon' - - # Not during the nap mode. - - condition: state - entity_id: input_boolean.nap_mode - state: 'off' - - action: - # Activate scene mode. - - service: input_boolean.turn_on - entity_id: input_boolean.scene_mode - - # Dim the spot lights. - - service: light.lifx_set_state - data: - entity_id: - - light.shower - - light.spotlight - data_template: - brightness: 100 - transition: 2 - - # If ceiling wash lights are on, set them to their dedicated Movie scene. - - condition: state - entity_id: group.ceiling - state: 'on' - - service: variable.set_variable - data: - variable: ceiling_effect - value: "Movie" - - # If the Aurora is active, set it to its dedicated Movie scene. - - condition: state - entity_id: light.aurora - state: 'on' - - service: variable.set_variable - data: - variable: aurora_effect - value: "Flames" - - service: variable.set_variable - data: - variable: aurora_brightness - value: "21" diff --git a/automations/media_player_start.yaml b/automations/media_player_start.yaml deleted file mode 100644 index d2c6988..0000000 --- a/automations/media_player_start.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# -# Media player starts, turn on mood lights -# -# Todo: revise the need for a movie scene. -# -# @subscribe input_boolean.nap_mode -# -- id: media_player_start - alias: Media player START - trigger: - # Kodi starts up. - - platform: state - entity_id: media_player.kodi - from: 'idle' - to: 'playing' - - condition: - # Sun has set. - - condition: state - entity_id: sun.sun - state: 'below_horizon' - - # Not during the nap mode. - - condition: state - entity_id: input_boolean.nap_mode - state: 'off' - - action: - - service: scene.turn_on - entity_id: scene.movies diff --git a/automations/media_player_stop.yaml b/automations/media_player_stop.yaml deleted file mode 100644 index 7eee53b..0000000 --- a/automations/media_player_stop.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# -# Media player paused/stopped. -# -# Todo: revise the need for a movie scene. -# -# @publish input_boolean.scene_mode -# -- id: media_player_stop - alias: Media player STOP - trigger: - # Kodi playback has been paused. - - platform: state - entity_id: media_player.kodi - to: 'paused' - - # Kodi playback has been stopped. - - platform: state - entity_id: media_player.kodi - to: 'idle' - - # Kodi has closed down. - - platform: state - entity_id: media_player.kodi - to: 'off' - - action: - # Disable the scene mode. - - service: input_boolean.turn_off - entity_id: input_boolean.scene_mode - - # Disable the scene. - - service: scene.turn_off - entity_id: scene.movies diff --git a/automations/motion_auto.yaml b/automations/motion_auto.yaml new file mode 100644 index 0000000..c964936 --- /dev/null +++ b/automations/motion_auto.yaml @@ -0,0 +1,21 @@ +# +# Warn when motion is detected +# +# @publish input_boolean.motion_detected +# +- id: motion_detection_auto + alias: Motion detection AUTO + trigger: + # When a motion detector has changed state. + - platform: state + entity_id: group.motion_sensors + + action: + # Toggle motion alert. + - service_template: >- + {% if is_state('group.motion_sensors', 'on') %} + input_boolean.turn_on + {% else %} + input_boolean.turn_off + {% endif %} + entity_id: input_boolean.motion_detected diff --git a/automations/nap_mode_start.yaml b/automations/nap_mode_start.yaml index 1fabdd6..b9f3407 100644 --- a/automations/nap_mode_start.yaml +++ b/automations/nap_mode_start.yaml @@ -1,8 +1,8 @@ # # When someone takes a nap # -# Should lower lights and minimize noises without preventing someone else -# from being active. +# Lowers lights and minimize noises without preventing someone else from being +# active. # # @publish input_boolean.nap_mode # @@ -11,7 +11,14 @@ - id: nap_mode_start alias: Nap mode START trigger: - # Bedsite Flic button is pressed once. + # When Minimote button 2 pressed once. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 3 # 3 = button #2 pressed once. + + # When bedside Flic button is pressed once. - platform: event event_type: flic_click event_data: diff --git a/automations/nap_mode_stop.yaml b/automations/nap_mode_stop.yaml index 1aa9d7b..74057e8 100644 --- a/automations/nap_mode_stop.yaml +++ b/automations/nap_mode_stop.yaml @@ -8,12 +8,14 @@ - id: nap_mode_stop alias: Nap mode STOP trigger: - # When night mode is enabled. - - platform: state - entity_id: input_boolean.night_mode - to: 'on' + # When Minimote button 2 pressed once. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 3 # 3 = button #2 pressed once. - # Bedsite Flic button is pressed once. + # When bedside Flic button is pressed once. - platform: event event_type: flic_click event_data: diff --git a/automations/night_mode_start.yaml b/automations/night_mode_start.yaml index e8f3110..f94b2f2 100644 --- a/automations/night_mode_start.yaml +++ b/automations/night_mode_start.yaml @@ -1,16 +1,21 @@ # # Enable night mode to shut off all lights # -# @subscribe input_boolean.nap_mode -# -# @publish input_boolean.nap_mode +# @publish input_boolean.night_mode # # @see /automations/quiet_mode_start.yaml # - id: night_mode_start alias: Night mode START trigger: - # Bedsite Flic button is held. + # When Minimote button 2 is held. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 4 # 4 = button #2 held. + + # When bedside Flic button is held. - platform: event event_type: flic_click event_data: @@ -18,7 +23,7 @@ click_type: hold condition: - # Not during the night mode. + # If night mode is not currently enabled. - condition: state entity_id: input_boolean.night_mode state: 'off' diff --git a/automations/night_mode_stop.yaml b/automations/night_mode_stop.yaml index e081b4f..8923e0d 100644 --- a/automations/night_mode_stop.yaml +++ b/automations/night_mode_stop.yaml @@ -1,16 +1,21 @@ # # Enable night mode to shut off all lights # -# @subscribe input_boolean.nap_mode -# -# @publish input_boolean.nap_mode +# @publish input_boolean.night_mode # # @see /automations/quiet_mode_start.yaml # - id: night_mode_stop alias: Night mode STOP trigger: - # Bedsite Flic button is held. + # When Minimote button 2 is held. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 4 # 4 = button #2 held. + + # When bedside Flic button is held. - platform: event event_type: flic_click event_data: @@ -18,7 +23,7 @@ click_type: hold condition: - # If during the night mode. + # If night mode is enabled. - condition: state entity_id: input_boolean.night_mode state: 'on' diff --git a/automations/nightlight_off.yaml b/automations/nightlight_off.yaml index bf9779a..4d354f1 100644 --- a/automations/nightlight_off.yaml +++ b/automations/nightlight_off.yaml @@ -1,22 +1,21 @@ # # Turn off nightlights when no longer needed # -# Todo: use an OFF timer instead of relying on motion detector. -# Todo: split motion detectors into their own automation + input_boolean.. -# Todo: map motion sensor state values to binary values. +# Todo: use an OFF timer instead of relying on motion detectors. # +# @subscribe input_boolean.motion_detected # @subscribe input_boolean.night_mode # - id: nightlight_off alias: Nightlight OFF trigger: - # Lounge motion no longer detected. + # Motion no longer detected. - platform: state - entity_id: sensor.aeotec_zw100_multisensor_6_burglar - to: '0' + entity_id: input_boolean.motion_detected + to: 'off' condition: - # If during the night mode. + # If it's during the night mode. - condition: state entity_id: input_boolean.night_mode state: 'on' @@ -26,6 +25,17 @@ - service: light.turn_off data: entity_id: - - light.shower - - light.spotlight + - group.lifx_lights transition: 10 + + # Disable dedicated kitchen night lights effect. + - service: homeassistant.turn_off + data: + entity_id: + - group.kitchen_lights + + # Turn off kiosk. + - service: homeassistant.turn_off + data: + entity_id: + - display.kiosk diff --git a/automations/nightlight_on.yaml b/automations/nightlight_on.yaml index 56a2a6c..b117fd8 100644 --- a/automations/nightlight_on.yaml +++ b/automations/nightlight_on.yaml @@ -1,36 +1,41 @@ # # Turn on nightlights when appropriate # -# Todo: split motion detectors into their own automation + input_boolean.. -# Todo: map motion sensor state values to binary values. -# +# @subscribe input_boolean.motion_detected # @subscribe input_boolean.night_mode # - id: nightlight_on alias: Nightlight ON trigger: - # Lounge motion detected. + # When motion is detected. - platform: state - entity_id: sensor.aeotec_zw100_multisensor_6_burglar - from: '0' - to: '8' + entity_id: input_boolean.motion_detected + to: 'on' condition: - # If during the night mode. + # If it's during the night mode. - condition: state entity_id: input_boolean.night_mode state: 'on' - # And the sun is still down. - - condition: sun - before: sunrise - action: # Turn night lights on. - service: light.turn_on data: entity_id: - - light.shower - - light.spotlight - brightness: 5 + - group.lifx_lights + brightness_pct: 8 transition: 5 + + # Enable dedicated kitchen night lights effect. + - service: homeassistant.turn_on + data: + entity_id: + - group.kitchen_lights + effect: night + + # Turn on kiosk. + - service: homeassistant.turn_on + data: + entity_id: + - display.kiosk diff --git a/automations/quiet_mode_start.yaml b/automations/quiet_mode_start.yaml index 61524a1..f05970b 100644 --- a/automations/quiet_mode_start.yaml +++ b/automations/quiet_mode_start.yaml @@ -1,24 +1,24 @@ # # When noise makers should not be running # -# @subscribe input_boolean.night_mode # @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode # # @publish input_boolean.quiet_mode # - id: quiet_mode_start alias: Quiet mode START trigger: - # It's too late. + # When it's too late. - platform: time at: '21:30:00' - # It's during sleep time. + # When night mode is enables. - platform: state entity_id: input_boolean.night_mode to: 'on' - # It's during nap time. + # When nap mode is enables. - platform: state entity_id: input_boolean.nap_mode to: 'on' diff --git a/automations/quiet_mode_stop.yaml b/automations/quiet_mode_stop.yaml index 352bc70..6a75ebd 100644 --- a/automations/quiet_mode_stop.yaml +++ b/automations/quiet_mode_stop.yaml @@ -1,42 +1,42 @@ # # When noise makers should be allowed to run # -# @subscribe input_boolean.night_mode # @subscribe input_boolean.nap_mode +# @subscribe input_boolean.night_mode # # @publish input_boolean.quiet_mode # - id: quiet_mode_stop alias: Quiet mode STOP trigger: - # It's daytime. + # When it's daytime. - platform: time at: '07:30:00' - # Sleep time is over. + # When night mode is over. - platform: state entity_id: input_boolean.night_mode from: 'on' to: 'off' - # Nap time is over. + # When nap mode is over. - platform: state entity_id: input_boolean.nap_mode from: 'on' to: 'off' condition: - # It has been quiet time. + # If it has been quiet mode. - condition: state entity_id: input_boolean.quiet_mode state: 'on' - # It's not during sleep time. + # If it's not during night mode. - condition: state entity_id: input_boolean.night_mode state: 'off' - # It's not during nap time. + # If it's not during nap mode. - condition: state entity_id: input_boolean.nap_mode state: 'off' diff --git a/automations/scene_daylight.yaml b/automations/scene_daylight.yaml new file mode 100644 index 0000000..bc735a4 --- /dev/null +++ b/automations/scene_daylight.yaml @@ -0,0 +1,29 @@ +# +# Toggle the daylight scene +# +# @publish input_select.scene +# +# @see /scripts/scene_daylight.yaml +# +- id: scene_daylight + alias: Scene DAYLIGHT + trigger: + # When Minimote button 1 is held. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 2 # 2 = button #1 held. + + action: + # Toggle the daylight scene. + - service: input_select.select_option + data: + entity_id: input_select.scene + data_template: + option: >- + {% if is_state('input_select.scene', 'Daylight') %} + Default + {% else %} + Daylight + {% endif %} diff --git a/automations/scene_gaming.yaml b/automations/scene_gaming.yaml new file mode 100644 index 0000000..c8d077d --- /dev/null +++ b/automations/scene_gaming.yaml @@ -0,0 +1,29 @@ +# +# Toggle the gaming scene +# +# @publish input_select.scene +# +# @see /scripts/scene_gaming.yaml +# +- id: scene_gaming + alias: Scene GAMING + trigger: + # When Minimote button 4 is clicked. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 7 # 7 = button #4 clicked. + + action: + # Toggle the gaming scene. + - service: input_select.select_option + data: + entity_id: input_select.scene + data_template: + option: >- + {% if is_state('input_select.scene', 'Gaming') %} + Default + {% else %} + Gaming + {% endif %} diff --git a/automations/scene_romantic.yaml b/automations/scene_romantic.yaml new file mode 100644 index 0000000..12708c1 --- /dev/null +++ b/automations/scene_romantic.yaml @@ -0,0 +1,36 @@ +# +# Toggle the romantic scene +# +# @publish input_select.scene +# +# @see /scripts/scene_romantic.yaml +# +- id: scene_romantic + alias: Scene ROMANTIC + trigger: + # When Minimote button 4 is held. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 8 # 8 = button #4 held. + + # When bedside Flic button is double-blocked. + - platform: event + event_type: flic_click + event_data: + button_name: flic_80e4da737711 + click_type: double + + action: + # Toggle the romantic scene. + - service: input_select.select_option + data: + entity_id: input_select.scene + data_template: + option: >- + {% if is_state('input_select.scene', 'Romantic') %} + Default + {% else %} + Romantic + {% endif %} diff --git a/automations/scene_select.yaml b/automations/scene_select.yaml new file mode 100644 index 0000000..eacdfab --- /dev/null +++ b/automations/scene_select.yaml @@ -0,0 +1,20 @@ +# +# Manually select a global scene +# +# @subscribe input_select.scene +# +# @see /scripts/ +# +- id: scene_select + alias: Scene SELECT + trigger: + # When a scene has been selected. + - platform: state + entity_id: input_select.scene + + action: + # Activate the global scene script. + - service: script.turn_on + data_template: + entity_id: >- + script.scene_{{ states('input_select.scene')|lower }} diff --git a/automations/tamper_notify.yaml b/automations/tamper_notify.yaml new file mode 100644 index 0000000..626fd00 --- /dev/null +++ b/automations/tamper_notify.yaml @@ -0,0 +1,34 @@ +# +# Warns someone if the tamper flag has changed +# +# @subscribe input_boolean.tamper_detected +# +- id: tamper_detection_notify + alias: Tamper detection NOTIFY + trigger: + # When the tamper flag has changed. + - platform: state + entity_id: input_boolean.tamper_detected + + action: + # Warn someone to take action. + - service: notify.text + data: + title: "Home security issue" + message: | + A perimeter device has been tampered with. + Current state: {% if is_state('input_boolean.tamper_detected', 'on') -%} + Tampered{% else %}Reset{% endif %} + Device: {{ states('variable.tamper_detected') }} + + # Pin a warning message in the frontend. + - condition: state + entity_id: input_boolean.tamper_detected + state: 'on' + - service: persistent_notification.create + data: + notification_id: security + title: "Home security issue" + message: | + A perimeter device has been tampered with at location: + {{ states('variable.tamper_detected') }}. diff --git a/automations/tamper_start.yaml b/automations/tamper_start.yaml new file mode 100644 index 0000000..593742d --- /dev/null +++ b/automations/tamper_start.yaml @@ -0,0 +1,30 @@ +# +# Warn when perimeter device is tempered with +# +# @publish input_boolean.tamper_detected +# +- id: tamper_detection_start + alias: Tamper detection START + trigger: + # When front door tamper is detected. + - platform: state + entity_id: sensor.front_door_burglar + from: '0' + + action: + # Record which devices are tampered with. + - service: variable.set_variable + data: + variable: tamper_detected + value_template: > + {% set value = '' %} + {% if not is_state('sensor.front_door_burglar', '0') %} + {% set value = value + 'Front Door,' %} + {% endif %} + + {{ value[:-1] }} + + # Enable tamper alert. + - service: input_boolean.turn_on + data: + entity_id: input_boolean.tamper_detected diff --git a/automations/tamper_stop.yaml b/automations/tamper_stop.yaml new file mode 100644 index 0000000..01a2946 --- /dev/null +++ b/automations/tamper_stop.yaml @@ -0,0 +1,18 @@ +# +# Reset flag when tampered devices have their alart reset +# +# @publish input_boolean.tamper_detected +# +- id: tamper_detection_start + alias: Tamper detection STOP + trigger: + # When front door tamper is no longer detected. + - platform: state + entity_id: sensor.front_door_burglar + to: '0' + + action: + # Disable tamper alert. + - service: input_boolean.turn_off + data: + entity_id: input_boolean.tamper_detected diff --git a/automations/theme_auto.yaml b/automations/theme_auto.yaml index 907cf21..c4dd3a6 100644 --- a/automations/theme_auto.yaml +++ b/automations/theme_auto.yaml @@ -11,12 +11,12 @@ - platform: homeassistant event: start - # If night mode is changed. + # When night mode is changed. - platform: state entity_id: input_boolean.night_mode action: - # Set theme to "normal" or "dark". + # Toggle theme between "normal" and "dark". - service: frontend.set_theme data_template: name: >- diff --git a/automations/check_update.yaml b/automations/update_notify.yaml similarity index 57% rename from automations/check_update.yaml rename to automations/update_notify.yaml index 94650d8..02843a6 100644 --- a/automations/check_update.yaml +++ b/automations/update_notify.yaml @@ -3,20 +3,16 @@ # # An updated Hass.io version usually follows shortly. # -- id: check_update_availability - alias: Check update availability +- id: update_notify + alias: Update NOTIFY trigger: - # If the updater service finds something new. + # When the updater service finds something new. platform: state entity_id: updater.updater action: - # Mark update as available. - - service: input_boolean.turn_on - entity_id: input_boolean.update_available - - # Send notification to owner. - - service: notify.group + # Send text notification to owner. + - service: notify.text data: title: "Home Assistant update" message: | diff --git a/automations/video_player_resume.yaml b/automations/video_player_resume.yaml new file mode 100644 index 0000000..1e5d7d6 --- /dev/null +++ b/automations/video_player_resume.yaml @@ -0,0 +1,104 @@ +# +# Media player plays video content +# +# This automation will kick in only if video playback is starting/resuming on an +# HTPC media player. Playing audio or anything else will not trigger the action. +# +# @subscribe input_boolean.nap_mode +# +# @publish input_select.scene +# +- id: video_player_resume + alias: Video player RESUME + trigger: + # When video media player resumes playback. + - platform: state + entity_id: + - media_player.kodi + - media_player.plex_htpc_chrome_lan + - media_player.plex_htpc_chrome_lan + - media_player.plex_htpc_firefox_lan + - media_player.plex_htpc_firefox_lan + - media_player.plex_htpc_microsoft_edge + - media_player.plex_htpc_microsoft_edge_lan + to: 'playing' + + condition: + # If the sun is set. + - condition: state + entity_id: sun.sun + state: 'below_horizon' + + # If it's not during the nap mode. + - condition: state + entity_id: input_boolean.nap_mode + state: 'off' + + # If we're playing videos. + - condition: template + value_template: >- + {{ + ( + is_state('media_player.kodi', 'playing') and + ( + is_state_attr('media_player.kodi', 'media_content_type', 'movie') or + is_state_attr('media_player.kodi', 'media_content_type', 'tvshow') or + is_state_attr('media_player.kodi', 'media_content_type', 'video') + ) + ) or + ( + is_state('media_player.plex_htpc_chrome', 'playing') and + ( + is_state_attr('media_player.plex_htpc_chrome', 'media_content_type', 'movie') or + is_state_attr('media_player.plex_htpc_chrome', 'media_content_type', 'tvshow') or + is_state_attr('media_player.plex_htpc_chrome', 'media_content_type', 'video') + ) + ) or + ( + is_state('media_player.plex_htpc_chrome_lan', 'playing') and + ( + is_state_attr('media_player.plex_htpc_chrome_lan', 'media_content_type', 'movie') or + is_state_attr('media_player.plex_htpc_chrome_lan', 'media_content_type', 'tvshow') or + is_state_attr('media_player.plex_htpc_chrome_lan', 'media_content_type', 'video') + ) + ) or + ( + is_state('media_player.plex_htpc_firefox', 'playing') and + ( + is_state_attr('media_player.plex_htpc_firefox', 'media_content_type', 'movie') or + is_state_attr('media_player.plex_htpc_firefox', 'media_content_type', 'tvshow') or + is_state_attr('media_player.plex_htpc_firefox', 'media_content_type', 'video') + ) + ) or + ( + is_state('media_player.plex_htpc_firefox_lan', 'playing') and + ( + is_state_attr('media_player.plex_htpc_firefox_lan', 'media_content_type', 'movie') or + is_state_attr('media_player.plex_htpc_firefox_lan', 'media_content_type', 'tvshow') or + is_state_attr('media_player.plex_htpc_firefox_lan', 'media_content_type', 'video') + ) + ) or + ( + is_state('media_player.plex_htpc_microsoft_edge', 'playing') and + ( + is_state_attr('media_player.plex_htpc_microsoft_edge', 'media_content_type', 'movie') or + is_state_attr('media_player.plex_htpc_microsoft_edge', 'media_content_type', 'tvshow') or + is_state_attr('media_player.plex_htpc_microsoft_edge', 'media_content_type', 'video') + ) + ) or + ( + is_state('media_player.plex_htpc_microsoft_edge_lan', 'playing') and + ( + is_state_attr('media_player.plex_htpc_microsoft_edge_lan', 'media_content_type', 'movie') or + is_state_attr('media_player.plex_htpc_microsoft_edge_lan', 'media_content_type', 'tvshow') or + is_state_attr('media_player.plex_htpc_microsoft_edge_lan', 'media_content_type', 'video') + ) + ) + }} + + action: + # Set the global scene to movies. + - service: input_select.select_option + data: + entity_id: input_select.scene + option: Movie diff --git a/automations/video_player_stop.yaml b/automations/video_player_stop.yaml new file mode 100644 index 0000000..30b1248 --- /dev/null +++ b/automations/video_player_stop.yaml @@ -0,0 +1,118 @@ +# +# Media player paused/stopped video content +# +# This automation only responds to the pausing/stopping of HTPC video playback. +# If music is playing on any HTPC media player then this automation will not +# perform its action. +# +# @publish input_select.scene +# +- id: video_player_stop + alias: Video player STOP + trigger: + # When media playback has been paused. + - platform: state + entity_id: + - media_player.kodi + - media_player.plex_htpc_chrome + - media_player.plex_htpc_chrome_lan + - media_player.plex_htpc_firefox + - media_player.plex_htpc_firefox_lan + - media_player.plex_htpc_microsoft_edge + - media_player.plex_htpc_microsoft_edge_lan + to: 'paused' + + # When media playback has been stopped. + - platform: state + entity_id: + - media_player.kodi + - media_player.plex_htpc_chrome + - media_player.plex_htpc_chrome_lan + - media_player.plex_htpc_firefox + - media_player.plex_htpc_firefox_lan + - media_player.plex_htpc_microsoft_edge + - media_player.plex_htpc_microsoft_edge_lan + to: 'idle' + + # When media player has been closed down. + - platform: state + entity_id: + - media_player.kodi + - media_player.plex_htpc_chrome + - media_player.plex_htpc_chrome_lan + - media_player.plex_htpc_firefox + - media_player.plex_htpc_firefox_lan + - media_player.plex_htpc_microsoft_edge + - media_player.plex_htpc_microsoft_edge_lan + to: 'off' + + condition: + # If no media player is showing video content. + - condition: template + value_template: >- + {{ + ( + not is_state('media_player.kodi', 'playing') or + ( + not is_state_attr('media_player.kodi', 'media_content_type', 'movie') and + not is_state_attr('media_player.kodi', 'media_content_type', 'tvshow') and + not is_state_attr('media_player.kodi', 'media_content_type', 'video') + ) + ) and + ( + not is_state('media_player.plex_htpc_chrome', 'playing') or + ( + not is_state_attr('media_player.plex_htpc_chrome', 'media_content_type', 'movie') and + not is_state_attr('media_player.plex_htpc_chrome', 'media_content_type', 'tvshow') and + not is_state_attr('media_player.plex_htpc_chrome', 'media_content_type', 'video') + ) + ) and + ( + not is_state('media_player.plex_htpc_chrome_lan', 'playing') or + ( + not is_state_attr('media_player.plex_htpc_chrome_lan', 'media_content_type', 'movie') and + not is_state_attr('media_player.plex_htpc_chrome_lan', 'media_content_type', 'tvshow') and + not is_state_attr('media_player.plex_htpc_chrome_lan', 'media_content_type', 'video') + ) + + ) and + ( + not is_state('media_player.plex_htpc_firefox', 'playing') or + ( + not is_state_attr('media_player.plex_htpc_firefox', 'media_content_type', 'movie') and + not is_state_attr('media_player.plex_htpc_firefox', 'media_content_type', 'tvshow') and + not is_state_attr('media_player.plex_htpc_firefox', 'media_content_type', 'video') + ) + ) and + ( + not is_state('media_player.plex_htpc_firefox_lan', 'playing') or + ( + not is_state_attr('media_player.plex_htpc_firefox_lan', 'media_content_type', 'movie') and + not is_state_attr('media_player.plex_htpc_firefox_lan', 'media_content_type', 'tvshow') and + not is_state_attr('media_player.plex_htpc_firefox_lan', 'media_content_type', 'video') + ) + ) and + ( + not is_state('media_player.plex_htpc_microsoft_edge', 'playing') or + ( + not is_state_attr('media_player.plex_htpc_microsoft_edge', 'media_content_type', 'movie') and + not is_state_attr('media_player.plex_htpc_microsoft_edge', 'media_content_type', 'tvshow') and + not is_state_attr('media_player.plex_htpc_microsoft_edge', 'media_content_type', 'video') + ) + ) and + ( + not is_state('media_player.plex_htpc_microsoft_edge_lan', 'playing') or + ( + not is_state_attr('media_player.plex_htpc_microsoft_edge_lan', 'media_content_type', 'movie') and + not is_state_attr('media_player.plex_htpc_microsoft_edge_lan', 'media_content_type', 'tvshow') and + not is_state_attr('media_player.plex_htpc_microsoft_edge_lan', 'media_content_type', 'video') + ) + ) + }} + + action: + # Return the global scene to default. + - service: input_select.select_option + data: + entity_id: input_select.scene + option: Default diff --git a/automations/wake_up.yaml b/automations/wake_up.yaml new file mode 100644 index 0000000..fcc50b5 --- /dev/null +++ b/automations/wake_up.yaml @@ -0,0 +1,20 @@ +# +# Wake up all devices +# +# @see /scripts/wake_up.yaml +# +- id: wake_up + alias: Wake up + trigger: + # When Minimote button 1 is clicked. + - platform: event + event_type: zwave.scene_activated + event_data: + entity_id: zwave.minimote + scene_id: 1 # 1 = button #1 clicked. + + action: + # Call the wake up sequence. + - service: script.turn_on + data: + entity_id: script.wake_up diff --git a/automations/washroom_off.yaml b/automations/washroom_off.yaml index c7df96b..74b0513 100644 --- a/automations/washroom_off.yaml +++ b/automations/washroom_off.yaml @@ -18,9 +18,9 @@ to: 'on' action: - # Turn off devices. + # Turn off all devices. - service: homeassistant.turn_off data: entity_id: - - group.washroom + - group.washroom_lights transition: 5 diff --git a/automations/washroom_on.yaml b/automations/washroom_on.yaml index 17ce093..440bdc1 100644 --- a/automations/washroom_on.yaml +++ b/automations/washroom_on.yaml @@ -29,9 +29,9 @@ state: 'off' action: - # Turn on devices. + # Turn on all devices. - service: homeassistant.turn_on data: entity_id: - - group.washroom + - group.washroom_lights transition: 5 diff --git a/cameras/README.md b/cameras/README.md index 80448ea..05892b9 100644 --- a/cameras/README.md +++ b/cameras/README.md @@ -1,18 +1,45 @@ # Cameras -I use camera sensors to fetch and display web images in [`/appdeamon/dashboards`](../appdeamon/dashboards). +I use camera sensors to fetch and display web images in [`/appdaemon/dashboards/`](../appdaemon/dashboards). +## Weather cameras -## Environment Canada radar maps +### [`📡 ./environment_canada.yaml`](environment_canada.yaml) -Rain and snow radar maps for the last 30 minutes or so, gathered to create simple animations in [`/appdeamon/dashboards/Weather.dash`](../appdeamon/dashboards/Weather.dash). +[Environment Canada](https://weather.gc.ca/radar/)'s rain and snow radar maps for the last 30 minutes or so, gathered to create simple animations in [`/appdaemon/dashboards/Weather.dash`](../appdaemon/dashboards/Weather.dash). +
+
+
+ Environment Canada rain radar map + Environment Canada snow radar map +
+
+

Environment Canada weather radar maps.

+
+
+
-## NOAA (U.S. National Oceanic and Atmospheric Administration) satellite imaging -Colourized and water vapour satellite images for the current air masses. Unlike the radar maps above these are not animated because precision is less relevant at those scales. +### [`🛰 ./noaa.yaml`](noaa.yaml) +NOAA's (U.S. National Oceanic and Atmospheric Administration) colourized and water vapour [GOES-East satellite images](https://www.star.nesdis.noaa.gov/GOES/GOES16_sectors.php?sector=ne) for the current air masses. Unlike the radar maps above these are not animated in the dashboards because precision is less relevant at those scales. -## Wallpapers +
+
+
+ NOAA GeoColour satellite image of North-America's East Coast + NOAA Water Vapour satellite image of North-America's East Coast +
+
+

NOAA GOES-East satellite images for North-America's East Coast.

+
+
+
-Pretty daily pictures from Bing and NASA, showcased in [`/appdeamon/dashboards/Main.dash`](../appdeamon/dashboards/Main.dash) + +## Other + +### [`🖼 ./wallpapers.yaml`](wallpapers.yaml) + +Pretty daily pictures from [Bing](http://bing.com) and [NASA](https://apod.nasa.gov/apod/astropix.html), showcased in [`/appdaemon/dashboards/Main.dash`](../appdaemon/dashboards/Main.dash) diff --git a/cameras/environment_canada.yaml b/cameras/environment_canada.yaml index c89adb6..a14c948 100644 --- a/cameras/environment_canada.yaml +++ b/cameras/environment_canada.yaml @@ -11,6 +11,8 @@ # @see /appdaemon/dashboards/Weather.dash # @see /groups/weather.yaml # +# @link https://weather.gc.ca/radar/ +# - platform: generic name: Environment Canada Rain scan_interval: 600 diff --git a/configuration.yaml b/configuration.yaml index 211b8c9..efcf9cd 100644 --- a/configuration.yaml +++ b/configuration.yaml @@ -35,7 +35,7 @@ config: # # @link https://home-assistant.io/components/conversation/ # -conversation: +# conversation: # @@ -43,8 +43,8 @@ conversation: # # @link https://github.com/andrey-git/home-assistant-customizer # -customizer: - custom_ui: local +# customizer: +# custom_ui: local # @@ -52,7 +52,7 @@ customizer: # # @link https://home-assistant.io/components/device_tracker/ # -#device_tracker: !include misc/device_trackers.yaml +device_tracker: !include misc/device_trackers.yaml # @@ -61,8 +61,16 @@ customizer: # @link https://home-assistant.io/components/discovery/ # discovery: - ignore: - - plex_mediaserver + + +# +# Displays +# +# @see /custom_components/display/ +# +# @link https://github.com/daemondazz/homeassistant-displays +# +display: !include misc/displays.yaml # @@ -71,6 +79,7 @@ discovery: # @link https://home-assistant.io/components/frontend/ # frontend: + # javascript_version: latest extra_html_url: - /local/custom_ui/state-card-custom-ui.html - /local/custom_ui/state-card-hline.html @@ -93,7 +102,7 @@ group: !include_dir_merge_named groups/ # # Enable the Hass.io panel # -hassio: +# hassio: # @@ -101,7 +110,7 @@ hassio: # # @link https://home-assistant.io/components/history/ # -history: +# history: # @@ -113,9 +122,19 @@ homeassistant: longitude: !secret zone_home_longitude elevation: !secret zone_home_elevation unit_system: metric - time_zone: America/Toronto + time_zone: !secret homeassistant_time_zone customize_glob: !include customize_glob.yaml customize: !include customize.yaml + whitelist_external_dirs: + - !secret homeassistant_whitelist_config + + +# +# HomeKit +# +# @link https://www.home-assistant.io/components/homekit/ +# +homekit: !include misc/homekit.yaml # @@ -126,6 +145,8 @@ homeassistant: http: # api_password: !secret http_password # base_url: !secret http_base_url + cors_allowed_origins: + - http://hassio.local:5050 # @@ -133,8 +154,8 @@ http: # # @link https://home-assistant.io/components/ifttt/ # -ifttt: - key: !secret ifttt_key +# ifttt: +# key: !secret ifttt_key # @@ -146,13 +167,22 @@ input_boolean: !include misc/input_booleans.yaml # -# Lists if selectable values +# Lists of selectable values # # @link https://home-assistant.io/components/input_select/ # input_select: !include misc/input_selects.yaml +# +# iOS companion component for the Home Assistant iOS app +# +# @link https://itunes.apple.com/us/app/home-assistant-open-source-home-automation/id1099568401 +# @link https://home-assistant.io/docs/ecosystem/ios/ +# +ios: + + # # Lights # @@ -166,18 +196,19 @@ light: !include_dir_merge_list lights/ # # @link https://home-assistant.io/components/logbook/ # -logbook: +# logbook: # # Log some details # -# @link https://home-assistant.io/components/frontend/ +# @link https://home-assistant.io/components/logger/ # logger: default: warning logs: - homeassistant.components.ebox: debug + custom_components.display: critical + homeassistant.components.notify.lannouncer: debug # @@ -185,7 +216,7 @@ logger: # # @link https://home-assistant.io/components/map/ # -map: +# map: # @@ -223,48 +254,7 @@ notify: !include_dir_merge_list notifications/ # # @link https://home-assistant.io/components/recorder/ # -recorder: - purge_interval: 2 - purge_keep_days: 5 - exclude: - domains: - - camera - - group - - light - - scene - - script - - sensor - - sun - - updater - - zone - - zwave - entities: - - switch.aeotec_zstick_disco_light - include: - entities: - - sensor.aqi - - sensor.aqi_carbon_monoxide - - sensor.aqi_carbon_monoxide_friendly - - sensor.aqi_friendly - - sensor.aqi_nitrogen_dioxide - - sensor.aqi_nitrogen_dioxide_friendly - - sensor.aqi_ozone - - sensor.aqi_ozone_friendly - - sensor.aqi_particles - - sensor.aqi_particles_friendly - - sensor.average_humidity - - sensor.average_humidity_friendly - - sensor.average_temperature - - sensor.bedroom_humidity - - sensor.bedroom_temperature - - sensor.lounge_humidity - - sensor.lounge_luminance - - sensor.lounge_temperature - - sensor.outside_humidity - - sensor.outside_temperature - - sensor.uv - - sensor.uv_friendly - - sensor.wind_speed +recorder: !include misc/recorder.yaml # @@ -272,7 +262,7 @@ recorder: # # @link https://home-assistant.io/components/scene/ # -scene: !include_dir_merge_list scenes/ +scene: !include misc/scenes.yaml # @@ -353,13 +343,16 @@ variable: !include misc/variables.yaml # # @link https://home-assistant.io/components/zone/ # -# zone: !include_dir_list zones/ +zone: !include misc/zones.yaml # # ZWave integration # +# @link https://home-assistant.io/docs/z-wave/adding/ +# @link https://home-assistant.io/docs/z-wave/ # @link https://home-assistant.io/components/zwave/ # zwave: usb_path: /dev/ttyACM0 + network_key: !secret zwave_network_key diff --git a/custom_components/README.md b/custom_components/README.md index c17a3a2..6e25e5d 100644 --- a/custom_components/README.md +++ b/custom_components/README.md @@ -3,15 +3,101 @@ ## Community components -- [`light/aurora.yaml`](light/aurora.yaml) opens communication with the [Nanoleaf Aurora](https://nanoleaf.me) using this [Hass.io-compatible fork](https://github.com/Oro/home-assistant/tree/light-aurora) of this [original component](https://github.com/software-2/ha-aurora). -- [`light/lightpack.yaml`](light/lightpack.yaml) supports basic operation of [Prismatik](https://github.com/psieg/Lightpack) monitor bias lighting using [Lightpack](https://github.com/kklemm91/Lightpack-HASS) -- [`sensor/doomsday_clock.yaml`](sensor/doomsday_clock.yaml) is a local copy of my depressing [Doomsday Clock](https://github.com/renemarc/home-assistant-custom-components) component. -- [`variable.yaml`](variables.yaml) is the missing link that allows storage of non-boolean values using the [Variable](https://github.com/rogro82/hass-variables) component. +### [`🎦 ./display/`](display) + +Interact with Android devices running the [Fully Kiosk Browser](https://www.ozerov.de/fully-kiosk-browser) by using this third-party [Display platform](https://github.com/daemondazz/homeassistant-displays). + +
+
+
+ Kiosk card +
+
+

Kiosk control.

+
+
+
+ + +### [`🔺 ./light/aurora.py`](light/aurora.py) + +Opens communication with the [Nanoleaf Aurora](https://nanoleaf.me) using this [Hass.io-compatible fork](https://github.com/Oro/home-assistant/tree/light-aurora) of this [original component](https://github.com/software-2/ha-aurora). + +
+
+
+ Nanoleaf Aurora card +
+
+

Nanoleaf Aurora control.

+
+
+
+ + +### [`📺 ./light/lightpack.py`](light/lightpack.py) + +Supports basic operation of [Prismatik](https://github.com/psieg/Lightpack) monitor bias lighting using this [Lightpack component](https://github.com/kklemm91/Lightpack-HASS). + +
+
+
+ Lightpack card +
+
+

Lightpack control.

+
+
+
+ + +### [`💀 ./sensor/doomsday_clock.py`](sensor/doomsday_clock.py) + +A local copy of my depressing [Doomsday Clock component](https://github.com/renemarc/home-assistant-custom-components) that tracks the _Bulletin of the Atomic Scientists_' [Minutes to Midnight](https://thebulletin.org/timeline) humanity status indicator. + +
+
+
+ Doomsday Clock card +
+
+

Doomsday Clock.

+
+
+
+ + +### [`❓ ./variable.py`](variables.py) + +The missing link that allows storage of non-boolean values using the [Variable component](https://github.com/rogro82/hass-variables). ## Overriden components -- [`sensor/ebox.yaml`](sensor/ebox.yaml): [EBox](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/sensor/ebox.py) - + Added support for "unlimited" values. -- [`sensor/gtfs.yaml`](sensor/gtfs.yaml): [GTFS](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/sensor/gtfs.py) - + Added support for next bus departures. +These are default Home Assistant components that were copied from the core to alter their behaviour. These changes really should be turned into appropriate [PRs](https://github.com/home-assistant/home-assistant/pulls). + + +### [`📡 ./sensor/ebox.py`](sensor/ebox.py) + +[Ebox](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/sensor/ebox.py) ISP data consumtion component: +- Upgraded [pyebox](https://github.com/titilambert/pyebox/) dependency to [support unlimited data packages](https://github.com/titilambert/pyebox/issues/1). + + +### [`🚌 ./sensor/gtfs.py`](sensor/gtfs.py) + +[GTFS](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/sensor/gtfs.py) public transit schedules component: +- Added support for next bus departures. +- Simplified query, making it cacheable in order to increase IO performance. +- Allow querying departures after midnight. +- Correctly set arrival date to tommorow when bus leaves before midnight but arrives after. + +
+
+
+ Public Transit group +
+
+

Public Transit group with schedules for the next three departures in two directions. Got to catch that bus! 🚌🏃

+
+
+
diff --git a/custom_components/customizer/__init__.py b/custom_components/customizer/__init__.py index 1f7ee17..570364b 100644 --- a/custom_components/customizer/__init__.py +++ b/custom_components/customizer/__init__.py @@ -85,7 +85,7 @@ def add_extra_html_url(base_url): .format(custom_ui)) component = EntityComponent(_LOGGER, DOMAIN, hass) - yield from component.async_add_entity(CustomizerEntity(config[DOMAIN])) + yield from component.async_add_entities([CustomizerEntity(config[DOMAIN])]) @callback def set_attribute(call): diff --git a/custom_components/display b/custom_components/display new file mode 160000 index 0000000..8fb4af3 --- /dev/null +++ b/custom_components/display @@ -0,0 +1 @@ +Subproject commit 8fb4af3a3461c6e64ebefb9a648b9b9549b10e95 diff --git a/custom_components/light/aurora.py b/custom_components/light/aurora.py index 8b451f0..2a9066b 100644 --- a/custom_components/light/aurora.py +++ b/custom_components/light/aurora.py @@ -14,9 +14,9 @@ import voluptuous as vol from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_HS_COLOR, SUPPORT_EFFECT, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, - SUPPORT_RGB_COLOR, PLATFORM_SCHEMA, Light) + SUPPORT_COLOR, PLATFORM_SCHEMA, Light) from homeassistant.const import CONF_HOST, CONF_TOKEN, CONF_NAME import homeassistant.helpers.config_validation as cv from homeassistant.util import color as color_util @@ -26,7 +26,7 @@ REQUIREMENTS = ['nanoleaf==0.4.1'] SUPPORT_AURORA = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT | - SUPPORT_RGB_COLOR) + SUPPORT_COLOR) _LOGGER = logging.getLogger(__name__) @@ -39,17 +39,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup Nanoleaf Aurora device.""" - from nanoleaf import Aurora + import nanoleaf host = config.get(CONF_HOST) name = config.get(CONF_NAME) token = config.get(CONF_TOKEN) - aurora_light = Aurora(host, token) + aurora_light = nanoleaf.Aurora(host, token) aurora_light.hass_name = name if aurora_light.on is None: _LOGGER.error("Could not connect to \ Nanoleaf Aurora: %s on %s", name, host) - add_devices([AuroraLight(aurora_light)]) + add_devices([AuroraLight(aurora_light)], True) class AuroraLight(Light): @@ -57,14 +57,14 @@ class AuroraLight(Light): def __init__(self, light): """Initialize an Aurora.""" - self._brightness = light.brightness - self._color_temp = light.color_temperature - self._effect = light.effect - self._effects_list = light.effects_list + self._brightness = None + self._color_temp = None + self._effect = None + self._effects_list = None self._light = light self._name = light.hass_name - self._rgb_color = light.rgb - self._state = light.on + self._hs_color = None + self._state = None @property def brightness(self): @@ -107,9 +107,9 @@ def is_on(self): return self._state @property - def rgb_color(self): - """Return the color in RGB.""" - return self._rgb_color + def hs_color(self): + """Return the color in HS.""" + return self._hs_color @property def supported_features(self): @@ -120,17 +120,14 @@ def turn_on(self, **kwargs): """Instruct the light to turn on.""" self._light.on = True brightness = kwargs.get(ATTR_BRIGHTNESS) - rgb_color = kwargs.get(ATTR_RGB_COLOR) + hs_color = kwargs.get(ATTR_HS_COLOR) color_temp_mired = kwargs.get(ATTR_COLOR_TEMP) effect = kwargs.get(ATTR_EFFECT) - if rgb_color: - self._light.rgb = rgb_color - # Aurora API automatically sets scene to 100 brightness - # This is to make sure that old brightness values are kept - # If brightness is also set in the same call, the value will - # be overwritten in a later block - self._light.brightness = self._brightness + if hs_color: + hue, saturation = hs_color + self._light.hue = int(hue) + self._light.saturation = int(saturation) if color_temp_mired: self._light.color_temperature = mired_to_kelvin(color_temp_mired) @@ -152,5 +149,5 @@ def update(self): self._color_temp = self._light.color_temperature self._effect = self._light.effect self._effects_list = self._light.effects_list - self._rgb_color = self._light.rgb + self._hs_color = self._light.hue, self._light.saturation self._state = self._light.on diff --git a/custom_components/sensor/doomsday_clock.py b/custom_components/sensor/doomsday_clock.py index e82b2e3..6a4615d 100644 --- a/custom_components/sensor/doomsday_clock.py +++ b/custom_components/sensor/doomsday_clock.py @@ -10,10 +10,10 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.doomsday_clock/ """ +import datetime import logging import re import voluptuous as vol -from datetime import timedelta from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.components.sensor.rest import RestData @@ -32,11 +32,11 @@ DEFAULT_ICON = 'mdi:nuke' DEFAULT_UNIT_OF_MEASUREMENT = 'min' -CONF_ATTRIBUTION = "Bulletin of the Atomic Scientists" +CONF_ATTRIBUTION = "Threat assessment by The Bulletin of the Atomic Scientists" CONF_RESOURCE = 'https://thebulletin.org/timeline' CONF_SELECTOR = '#content .view-content .node-title' -MIN_TIME_BETWEEN_UPDATES = timedelta(hours=1) +MIN_TIME_BETWEEN_UPDATES = datetime.timedelta(hours=1) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, @@ -113,7 +113,8 @@ def device_state_attributes(self): """Return the state attributes.""" return { ATTR_ATTRIBUTION: CONF_ATTRIBUTION, - "minutes_to_midnight": self._sentence, + "countdown": self._sentence, + "time": self.numberToTime(), } @property @@ -162,6 +163,15 @@ def sentenceToNumber(self, sentence): 'Could not find pattern "%s" in sentence "%s"', pattern, sentence) + def numberToTime(self): + midnight = datetime.datetime.combine(datetime.date.today() + datetime.timedelta(days=1), datetime.time(0, 0, 0, 0)) + minutes = self._state // 1 + seconds = (self._state - minutes) * 60 + delta = datetime.timedelta(minutes=minutes, seconds=seconds) + + return (midnight - delta).strftime('%H:%M:%S') + + @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Get the latest data from the source and updates the state.""" diff --git a/custom_components/sensor/ebox.py b/custom_components/sensor/ebox.py index dc4637d..071c84f 100644 --- a/custom_components/sensor/ebox.py +++ b/custom_components/sensor/ebox.py @@ -19,7 +19,9 @@ CONF_NAME, CONF_MONITORED_VARIABLES) from homeassistant.helpers.entity import Entity -REQUIREMENTS = ['pyebox==1.0.1'] +REQUIREMENTS = ["https://github.com/titilambert/pyebox/archive/" + "741d7be7ddb0e2c641877fb43b860a2fbfd11d5e.zip#" + "pyebox==0.1.1"] _LOGGER = logging.getLogger(__name__) @@ -70,7 +72,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): ebox_data = EBoxData(username, password) ebox_data.update() except requests.exceptions.HTTPError as error: - _LOGGER.error("Failt login: %s", error) + _LOGGER.error("Failed login: %s", error) return False name = config.get(CONF_NAME) diff --git a/custom_components/sensor/gtfs.py b/custom_components/sensor/gtfs.py index ff8bec8..af93621 100644 --- a/custom_components/sensor/gtfs.py +++ b/custom_components/sensor/gtfs.py @@ -41,8 +41,7 @@ vol.Required(CONF_DESTINATION): cv.string, vol.Required(CONF_DATA): cv.string, vol.Optional(CONF_NAME): cv.string, - vol.Optional(CONF_OFFSET, default=datetime.timedelta(0)): - cv.time_period_dict, + vol.Optional(CONF_OFFSET, default=0): cv.time_period, vol.Optional(CONF_POSITION, default=DEFAULT_POSITION): cv.positive_int, }) @@ -56,8 +55,10 @@ def get_next_departure(sched, start_station_id, end_station_id, offset, now = datetime.datetime.now() + offset day_name = now.strftime('%A').lower() now_str = now.strftime('%H:%M:%S') + now_time = now.time() today = now.strftime('%Y-%m-%d') - + tomorrow_obj = datetime.date.today() + datetime.timedelta(days=1) + tomorrow = tomorrow_obj.strftime('%Y-%m-%d') skip = int(position) - 1 from sqlalchemy.sql import text @@ -92,29 +93,36 @@ def get_next_departure(sched, start_station_id, end_station_id, offset, INNER JOIN stops end_station ON destination_stop_time.stop_id = end_station.stop_id WHERE calendar.{day_name} = 1 - AND time(origin_stop_time.departure_time) > time(:now_str) AND start_station.stop_id = :origin_station_id - AND end_station.stop_id = :end_station_id + AND end_station.stop_id = :end_station_id AND origin_stop_time.stop_sequence < destination_stop_time.stop_sequence AND calendar.start_date <= :today AND calendar.end_date >= :today ORDER BY origin_stop_time.departure_time - LIMIT 1 OFFSET :skip; """.format(day_name=day_name)) - result = sched.engine.execute(sql_query, now_str=now_str, + result = sched.engine.execute(sql_query, origin_station_id=origin_station.id, end_station_id=destination_station.id, - today=today, - skip=skip) + today=today) + + rows = result.fetchall() item = {} - for row in result: - item = row + for i,row in enumerate(rows): + if (datetime.datetime.strptime(row[2], '%H:%M:%S').time() > now_time): + schedule_idx = i + skip + if schedule_idx < len(rows): + item = rows[schedule_idx] + if (datetime.datetime.strptime(item[2], '%H:%M:%S').time() + <= now_time): + today = tomorrow + break if item == {}: return None departure_time_string = '{} {}'.format(today, item[2]) - arrival_time_string = '{} {}'.format(today, item[3]) + arrival_time_string = '{} {}'.format(today if item[3] > item[2] + else tomorrow, item[3]) departure_time = datetime.datetime.strptime(departure_time_string, TIME_FORMAT) arrival_time = datetime.datetime.strptime(arrival_time_string, @@ -127,8 +135,10 @@ def get_next_departure(sched, start_station_id, end_station_id, offset, origin_stoptime_arrival_time = '{} {}'.format(today, item[4]) origin_stoptime_departure_time = '{} {}'.format(today, item[5]) - dest_stoptime_arrival_time = '{} {}'.format(today, item[11]) - dest_stoptime_depart_time = '{} {}'.format(today, item[12]) + dest_stoptime_arrival_time = '{} {}'.format(today if item[11] > item[5] + else tomorrow, item[11]) + dest_stoptime_depart_time = '{} {}'.format(today if item[12] > item[5] + else tomorrow, item[12]) origin_stop_time_dict = { 'Arrival Time': origin_stoptime_arrival_time, diff --git a/custom_components/variable.py b/custom_components/variable.py index 209d34e..cd7d5b9 100644 --- a/custom_components/variable.py +++ b/custom_components/variable.py @@ -85,7 +85,7 @@ def async_set_variable_service(call): """Handle calls to the set_variable service.""" entity_id = ENTITY_ID_FORMAT.format(call.data.get(ATTR_VARIABLE)) - entity = component.entities[entity_id] + entity = component.get_entity(entity_id) if entity: target_variables = [ entity ] diff --git a/customize.yaml b/customize.yaml index 8ffd5f8..bfa8ae6 100644 --- a/customize.yaml +++ b/customize.yaml @@ -1,27 +1,42 @@ # # Automations # -automation.cct: - icon: mdi:white-balance-auto -automation.check_door_left_open: +automation.daily_greeting: + icon: mdi:human-greeting +automation.humidity_notify: + icon: mdi:water-percent +automation.front_door_notify: icon: mdi:door-open -automation.check_mold_conditions: - icon: mdi:biohazard -automation.check_update_availability: - icon: mdi:cloud-upload automation.go_to_sleep: icon: mdi:weather-night automation.theme_auto: icon: mdi:theme-light-dark -automation.wake_up: +automation.scene_daylight: icon: mdi:weather-sunny +automation.scene_gaming: + icon: mdi:google-controller +automation.scene_romantic: + icon: mdi:home-heart +automation.scene_select: + icon: mdi:looks +automation.update_notify: + icon: mdi:cloud-upload +automation.wake_up: + icon: mdi:power # # Binary sensors # +binary_sensor.flic_80e4da72e890: + friendly_name: Flic white binary_sensor.flic_80e4da737711: friendly_name: Flic blue +binary_sensor.lounge_multisensor_sensor: + device_class: motion + group: + group.lounge: + friendly_name: Motion # @@ -43,10 +58,30 @@ camera.noaa_water_vapour: device_tracker.cellphone_her: friendly_name: !secret nickname_her icon: mdi:cellphone-iphone + extra_data_template: + - >- + ${entities['device_tracker.laptop_her'].attributes['friendly_name']} is + ${entities['device_tracker.laptop_her'].state}. device_tracker.cellphone_him: friendly_name: !secret nickname_him - gravatar: !secret gravatar_him icon: mdi:cellphone-iphone + extra_data_template: + - >- + ${entities['device_tracker.laptop_him'].attributes['friendly_name']} is + ${entities['device_tracker.laptop_him'].state}. +device_tracker.laptop_her: + friendly_name: Her laptop + icon: mdi:laptop +device_tracker.laptop_him: + friendly_name: His laptop + icon: mdi:laptop + + +# +# Displays +# +display.kiosk: + icon: mdi:tablet # @@ -67,16 +102,18 @@ group.weather_view: # # Input booleans # -input_boolean.low_mode: - icon: mdi:weather-sunset-down -input_boolean.nap_mode: - icon: mdi:sleep -input_boolean.night_mode: - icon: mdi:weather-night -input_boolean.quiet_mode: - icon: mdi:volume-mute -input_boolean.scene_mode: - icon: mdi:looks +input_boolean.motion_detected: + confirm_controls_show_lock: true + templates: + theme: >- + return state == 'on' ? 'card-warning' + : null; +input_boolean.tamper_detected: + confirm_controls_show_lock: true + templates: + theme: >- + return state == 'on' ? 'card-critical' + : null; # @@ -90,6 +127,8 @@ input_select.bed_effect: input_select.ceiling_effect: friendly_name: Effect icon: mdi:blank +input_select.lightpack_effect: + icon: mdi:blank # @@ -115,6 +154,7 @@ light.bedroom: entities['sensor.ceiling_effect_loaded'].state : null; icon: mdi:led-strip + homebridge_hidden: false slider_theme: max: 255 min: 0 @@ -124,10 +164,12 @@ light.bedroom: light.countertop: extra_data_template: >- return (attributes.brightness) ? - Math.round(650 - (attributes.color_temp - 154) * 380 / 346) * 10 + ' K @ ' + + Math.round(1000000 / attributes.color_temp / 50) * 50 + ' K @ ' + Math.round(attributes.brightness / 255 * 100) + '%' : null; + homebridge_hidden: false icon: mdi:border-top + assumed_state: false slider_theme: max: 255 min: 0 @@ -137,10 +179,12 @@ light.countertop: light.island: extra_data_template: >- return (attributes.brightness) ? - Math.round(650 - (attributes.color_temp - 154) * 380 / 346) * 10 + ' K @ ' + + Math.round(1000000 / attributes.color_temp / 50) * 50 + ' K @ ' + Math.round(attributes.brightness / 255 * 100) + '%' : null; + homebridge_hidden: false icon: mdi:table-column + assumed_state: false slider_theme: max: 255 min: 0 @@ -149,10 +193,11 @@ light.island: report_when_not_changed: false light.headboard: extra_data_template: >- - return (state === 'on' && entities['sensor.bed_effect_loaded'].state) ? + return (state === 'on' && entities['sensor.bed_effect_loaded'].state) ? entities['sensor.bed_effect_loaded'].state : null; icon: mdi:gate + homebridge_hidden: false slider_theme: max: 255 min: 0 @@ -160,6 +205,10 @@ light.headboard: pin: true report_when_not_changed: false light.lightpack: + extra_data_template: >- + return (state === 'on' && entities['sensor.lightpack_effect_loaded'].state) ? + entities['sensor.lightpack_effect_loaded'].state + : null; homebridge_hidden: false icon: mdi:television light.lounge: @@ -167,6 +216,7 @@ light.lounge: return (state === 'on' && entities['sensor.ceiling_effect_loaded'].state) ? entities['sensor.ceiling_effect_loaded'].state : null; + homebridge_hidden: false icon: mdi:led-strip slider_theme: max: 255 @@ -177,10 +227,12 @@ light.lounge: light.microwave: extra_data_template: >- return (attributes.brightness) ? - Math.round(650 - (attributes.color_temp - 154) * 380 / 346) * 10 + ' K @ ' + + Math.round(1000000 / attributes.color_temp / 50) * 50 + ' K @ ' + Math.round(attributes.brightness / 255 * 100) + '%' : null; + homebridge_hidden: false icon: mdi:gradient + assumed_state: false slider_theme: max: 255 min: 0 @@ -189,9 +241,10 @@ light.microwave: report_when_not_changed: false light.middle: extra_data_template: >- - return (state === 'on' && entities['sensor.ceiling_effect_loaded'].state) ? + return (state === 'on' && entities['sensor.ceiling_effect_loaded'].state) ? entities['sensor.ceiling_effect_loaded'].state : null; + homebridge_hidden: false icon: mdi:led-strip slider_theme: max: 255 @@ -202,7 +255,7 @@ light.middle: light.shower: extra_data_template: >- return (attributes.brightness) ? - Math.round(1000000 / attributes.color_temp / 10) * 10 + ' K @ ' + + Math.round(1000000 / attributes.color_temp / 50) * 50 + ' K @ ' + Math.round(attributes.brightness / 255 * 100) + '%' : null; icon: mdi:spotlight @@ -216,10 +269,12 @@ light.shower: light.sink: extra_data_template: >- return (attributes.brightness) ? - Math.round(650 - (attributes.color_temp - 154) * 380 / 346) * 10 + ' K @ ' + + Math.round(1000000 / attributes.color_temp / 50) * 50 + ' K @ ' + Math.round(attributes.brightness / 255 * 100) + '%' : null; + homebridge_hidden: false icon: mdi:water-pump + assumed_state: false slider_theme: max: 255 min: 0 @@ -229,7 +284,7 @@ light.sink: light.spotlight: extra_data_template: >- return (attributes.brightness) ? - Math.round(1000000 / attributes.color_temp / 10) * 10 + ' K @ ' + + Math.round(1000000 / attributes.color_temp / 50) * 50 + ' K @ ' + Math.round(attributes.brightness / 255 * 100) + '%' : null; icon: mdi:spotlight-beam @@ -242,10 +297,11 @@ light.spotlight: state_card_mode: break-slider light.underbed: extra_data_template: >- - return (state === 'on' && entities['sensor.bed_effect_loaded'].state) ? + return (state === 'on' && entities['sensor.bed_effect_loaded'].state) ? entities['sensor.bed_effect_loaded'].state : null; icon: mdi:hotel + homebridge_hidden: false slider_theme: max: 255 min: 0 @@ -259,19 +315,25 @@ light.underbed: # sensor.bing_wallpaper_info: custom_ui_state_card: state-card-value_only -sensor.date_friendly: - friendly_name: " " - extra_data_template: >- - ${entities['sensor.day'].state} - theme: card-secondary-title -sensor.hline_dashed: - config: - width: 90 - height: 0 - backgroundcolor: inherit - bordertop: '1px dashed silver' sensor.good_vibes: custom_ui_state_card: state-card-value_only +sensor.doors_status: + templates: + theme: >- + return state != 'Closed' ? 'card-warning' + : null; +sensor.tamper_status: + templates: + theme: >- + return state != 'OK' + ? entities['input_boolean.tamper_detected'].state == 'on' ? 'card-critical' + : 'card-warning' + : null; +sensor.motion_status: + templates: + theme: >- + return state != 'OK' ? 'card-warning' + : null; # @@ -392,6 +454,18 @@ sensor.aqi_particles_friendly: return v > 100 ? 'card-critical' : v > 50 ? 'card-warning' : null; +sensor.aqi_sulphur_dioxide_friendly: + extra_data_template: >- + return entities['sensor.aqi_sulphur_dioxide'].state != 'unknown' ? + entities['sensor.aqi_sulphur_dioxide'].state + ' ' + + entities['sensor.aqi_sulphur_dioxide'].attributes['unit_of_measurement'] + : null; + templates: + theme: >- + var v = parseInt(entities['sensor.aqi_sulphur_dioxide'].state); + return v > 100 ? 'card-critical' + : v > 50 ? 'card-warning' + : null; sensor.uv_friendly: extra_badge: entity_id: sensor.uv @@ -419,6 +493,13 @@ sensor.front_door_sensor_battery: icon: mdi:door group.kitchen: friendly_name: Front Door Battery +sensor.kiosk_battery: + group: + group.battery: + friendly_name: Kiosk + icon: mdi:tablet + group.kitchen: + friendly_name: Kiosk Battery sensor.lounge_multisensor_battery: group: group.battery: @@ -431,16 +512,14 @@ sensor.lounge_multisensor_battery: # # Sensors: System # -sensor.cpu_used: +sensor.processor_use: friendly_name: CPU Load icon: mdi:chip extra_data_template: >- return entities['sensor.average_load'].state + ' ' + '(' + entities['sensor.cpu_cores'].state + ' cores)'; -sensor.database_size: - icon: mdi:database -sensor.disk_used_percent: +sensor.disk_use_percent: extra_data_template: >- return Math.round(parseFloat(entities['sensor.disk_free_home'].state)) + ' ' + @@ -457,13 +536,11 @@ sensor.ebox_usage: friendly_name: Monthly usage sensor.ipv4_address_eth0: friendly_name: Local IP Address -sensor.logfile_size: - icon: mdi:history -sensor.ram_used_percent: +sensor.memory_use_percent: extra_data_template: >- return - Math.round(parseFloat(entities['sensor.ram_available'].state)) + ' ' + - entities['sensor.ram_available'].attributes['unit_of_measurement'] + + Math.round(parseFloat(entities['sensor.memory_free'].state)) + ' ' + + entities['sensor.memory_free'].attributes['unit_of_measurement'] + ' available'; sensor.speedtest_download: friendly_name: Downspeed @@ -471,6 +548,7 @@ sensor.speedtest_download: show_last_changed: true sensor.speedtest_ping: friendly_name: Ping + icon: mdi:timer show_last_changed: true sensor.speedtest_upload: friendly_name: Upspeed @@ -544,17 +622,14 @@ sensor.dark_sky_summary: sensor.weather_details: custom_ui_state_card: state-card-value_only sensor.wind_speed: - friendly_name: " " extra_badge: entity_id: sensor.wind_bearing_cardinal - extra_data_template: >- - ${entities['sensor.wind_scale_friendly'].state} templates: theme: >- var v = parseInt(state); return v >= 89 ? 'card-critical' : v >= 39 ? 'card-warning' - : 'card-secondary-title'; + : null; # # Scenes @@ -596,4 +671,28 @@ switch.souvenirs_light: friendly_name: Souvenirs Light icon: mdi:trophy switch.window_light: + homebridge_hidden: false icon: mdi:creation + + +# +# Updater +# +updater.updater: + custom_ui_state_card: state-card-custom-ui + extra_data_template: >- + Current version: ${entities['sensor.current_version'].state} + + +# +# Variables +# +variable.tamper_detected: + friendly_name: Tamper location + icon: mdi:security-home + templates: + theme: >- + return state != 'False' + ? entities['input_boolean.tamper_detected'].state == 'on' ? 'card-critical' + : 'card-warning' + : null; diff --git a/customize_glob.yaml b/customize_glob.yaml index 7e9bf87..0e927e8 100644 --- a/customize_glob.yaml +++ b/customize_glob.yaml @@ -19,20 +19,26 @@ automation.bed_*: icon: mdi:hotel automation.bedroom_*: icon: mdi:hotel +automation.cct_*: + icon: mdi:white-balance-auto automation.ceiling_*: icon: mdi:led-strip -automation.check_humidity_*: - icon: mdi:water-percent automation.dehumidifier_*: icon: mdi:water-off -automation.front_door_*: - icon: mdi:door +automation.doors_*: + icon: mdi:door-open +automation.kitchen_*: + icon: mdi:food-fork-drink +automation.kiosk_*: + icon: mdi:tablet +automation.lightpack_*: + icon: mdi:television automation.lounge_*: icon: mdi:sofa automation.low_power_mode_*: icon: mdi:weather-sunset-down -automation.media_player_*: - icon: mdi:kodi +automation.motion_*: + icon: mdi:run automation.nap_mode_*: icon: mdi:sleep automation.nightlight_*: @@ -41,6 +47,10 @@ automation.night_mode_*: icon: mdi:weather-night automation.quiet_mode_*: icon: mdi:volume-mute +automation.tamper_*: + icon: mdi:security-home +automation.video_player_*: + icon: mdi:plex automation.washroom_*: icon: mdi:water-pump @@ -92,3 +102,9 @@ sensor.[!dark_sky]*_temperature: friendly_name: Temperature sensor.hline_*: custom_ui_state_card: state-card-hline +sensor.hline_dashed*: + config: + width: 90 + height: 0 + backgroundcolor: inherit + bordertop: '1px dashed silver' diff --git a/entity_registry.yaml b/entity_registry.yaml new file mode 100644 index 0000000..03cf8ed --- /dev/null +++ b/entity_registry.yaml @@ -0,0 +1,96 @@ +light.bedroom: + platform: lifx + unique_id: d0:73:d5:15:17:21 +light.headboard: + platform: lifx + unique_id: d0:73:d5:14:f8:8c +light.lounge: + platform: lifx + unique_id: d0:73:d5:14:f7:4d +light.lounge_lamp: + platform: lifx + unique_id: d0:73:d5:31:37:8c +light.middle: + platform: lifx + unique_id: d0:73:d5:14:fc:08 +light.shower: + platform: lifx + unique_id: d0:73:d5:25:7e:a8 +light.spotlight: + platform: lifx + unique_id: d0:73:d5:25:43:1c +light.underbed: + platform: lifx + unique_id: d0:73:d5:15:0c:ae +binary_sensor.front_door_sensor: + platform: zwave + unique_id: 4-72057594110017536 +binary_sensor.lounge_multisensor_sensor: + platform: zwave + unique_id: 5-72057594126794752 +sensor.front_door_alarm_type: + platform: zwave + unique_id: 4-72057594111082497 +sensor.front_door_alarm_level: + platform: zwave + unique_id: 4-72057594111082513 +sensor.front_door_sourcenodeid: + platform: zwave + unique_id: 4-72057594111082529 +sensor.front_door_access_control: + platform: zwave + unique_id: 4-72057594111082641 +sensor.front_door_burglar: + platform: zwave + unique_id: 4-72057594111082657 +sensor.lounge_multisensor_temperature: + platform: zwave + unique_id: 5-72057594126811154 +sensor.lounge_multisensor_luminance: + platform: zwave + unique_id: 5-72057594126811186 +sensor.lounge_multisensor_relative_humidity: + platform: zwave + unique_id: 5-72057594126811218 +sensor.lounge_multisensor_ultraviolet: + platform: zwave + unique_id: 5-72057594126811570 +sensor.lounge_multisensor_alarm_type: + platform: zwave + unique_id: 5-72057594127859713 +sensor.lounge_multisensor_alarm_level: + platform: zwave + unique_id: 5-72057594127859729 +sensor.lounge_multisensor_sourcenodeid: + platform: zwave + unique_id: 5-72057594127859745 +sensor.lounge_multisensor_burglar: + platform: zwave + unique_id: 5-72057594127859873 +sensor.renemarc_iphone_battery_state: + platform: ios + unique_id: state_cellphone_him +sensor.renemarc_iphone_battery_level: + platform: ios + unique_id: level_cellphone_him +media_player.plex_htpc_chrome: + platform: plex + unique_id: evqqz9dhn5ijqezbt9bx5euk +media_player.plex_htpc_chrome_lan: + platform: plex + unique_id: 2geodce3554zd0j7kixyfnzi +media_player.plex_htpc_firefox: + platform: plex + unique_id: 87rcsmjonu5jvqo3853ihba0 +media_player.plex_htpc_firefox_lan: + platform: plex + unique_id: k14b49ckgpehqp0avovuh9r2 +media_player.plex_htpc_microsoft_edge: + platform: plex + unique_id: db63di3hgp091n4d3jflkpv2 +media_player.plex_htpc_microsoft_edge_lan: + platform: plex + unique_id: jc7yjwset23kx7plhdfckise +media_player.plex_mac_firefox_lan: + platform: plex + unique_id: uwfbjj7g2w8zhbgl15rli4e4 diff --git a/groups/README.md b/groups/README.md index 4639ed8..6b4d62f 100644 --- a/groups/README.md +++ b/groups/README.md @@ -5,40 +5,133 @@ To avoid a mess of sensors, the state cards are placed into different pages (vie ## Organization -Views are split into 5 pages, organized in a similar fashion as [`/appdaemon/dashboards`](../appdaemon/dashboards) only with more administrative features. +Views are split into 5 pages, organized in a similar fashion as [`/appdaemon/dashboards/`](../appdaemon/dashboards) only with more administrative features. -### Default page [`default.yaml`](default.yaml) +### [`🏠 ./default.yaml`](default.yaml) With regular actions, climate control, bus schedules and a pretty picture of the day. +
+
+
+ Home menu option +
+
+ Date group + Presence group + Climate Control group + Security Status group + Actions group + Public Transit group +
+
+

Default view groups.

+
+
+
+ + +### [`🔘 ./switchboard.yaml`](switchboard.yaml) + +Organized by room and control zone. + +
+
+
+ Switchboard menu option +
+
+ Kitchen group + Ceiling Wash Lights group + Lounge group + Bedroom group + Washroom group +
+
+

Switchboard view groups.

+
+
+
+ + +### [`🌦 ./weather.yaml`](weather.yaml) -### Switchboard [`switchboard.yaml`](switchboard.yaml) - -Organized my room and control zone. +With current conditions, forecasts, air quality, radar and satellite maps. +
+
+
+ Weather menu option +
+
+ Today's Weather group + Weekly Forecast group + Environment Canada rain radar map + Environment Canada snow radar map + NOAA GeoColour satellite image + NOAA Water Vapour satellite image + Atmospheric Safety group +
+
+

Weather view groups.

+
+
+
+ + +### [`👀 ./status.yaml`](status.yaml) -### Weather [`weather.yaml`](weather.yaml) +Geeky details about Home Assistant, network, battery status and per-location temperature and humidity. -With current conditions, forecasts, air quality, radar and satellite maps. +
+
+
+ Status menu option +
+
+ System group + Network group + Temperature group + Humidity group + Battery group +
+
+

Status view cards.

+
+
+
+ + +### [`⚙ ./configuration.yaml`](configuration.yaml) -

- Current conditions - Forecast -

+States and automation overrides. -### Status [`status.yaml`](status.yaml) +
+
+
+ Configuration menu option +
+
+ Modes group + Configuration group +
+
+

Some configuration view cards.

+
+
+
-Geeky details about Home Assistant, network, battery status and per-location temperature and humidity. +## Other -### Configuration [`configuration.yaml`](configuration.yaml) +### [`🙈 ./invisible.yaml`](invisible.yaml) -States and automation overrides. +For logical groups referenced in code but not displayed in views. ## Customization The bulk of the customization is done in [`/customize.yaml`](../customize.yaml) and [`/customize_glob.yaml`](../customize_glob.yaml). -The looks of many state cards depend on Custom UI and other templates in [`/www/custom_ui`](../www/custom_ui). +The looks of many state cards depend on Custom UI and other templates in [`/www/custom_ui/`](../www/custom_ui). diff --git a/groups/configuration.yaml b/groups/configuration.yaml index 45bb674..242b912 100644 --- a/groups/configuration.yaml +++ b/groups/configuration.yaml @@ -26,21 +26,29 @@ modes: - input_boolean.quiet_mode - input_boolean.low_mode - input_boolean.scene_mode + - input_boolean.motion_detected + - input_boolean.tamper_detected + - variable.tamper_detected automations: name: Automations control: hidden entities: - - automation.cct - - automation.check_door_left_open - - automation.check_humidity_high - - automation.check_humidity_low - - automation.check_mold_conditions - - automation.check_update_availability - - automation.front_door_closed - - automation.front_door_opened + - automation.cct_lifx + - automation.cct_limitlessled + - automation.daily_greeting + - automation.doors_notify + - automation.doors_verify + - automation.front_door_notify - automation.go_to_sleep + - automation.humidity_notify + - automation.scene_daylight + - automation.scene_gaming + - automation.scene_romantic + - automation.scene_select + - automation.tamper_detection_notify - automation.theme_auto + - automation.update_notify - automation.wake_up automations_areas: @@ -50,12 +58,14 @@ automations_areas: - automation.bedroom_low_power - automation.bedroom_off - automation.bedroom_on - - automation.ceiling_default - automation.ceiling_effect - automation.ceiling_off - automation.ceiling_on - automation.ceiling_schedule - automation.ceiling_select + - automation.kitchen_low_power + - automation.kitchen_off + - automation.kitchen_on - automation.lounge_low_power - automation.lounge_off - automation.lounge_on @@ -68,21 +78,28 @@ automations_devices: control: hidden entities: - automation.aurora_brightness - - automation.aurora_default - automation.aurora_effect - automation.aurora_schedule - automation.aurora_select - - automation.bed_default - automation.bed_effect - automation.bed_schedule - automation.bed_select - automation.dehumidifier_off - automation.dehumidifier_on - - automation.media_player_resume - - automation.media_player_start - - automation.media_player_stop + - automation.kitchen_lights_full + - automation.kitchen_lights_init + - automation.kitchen_lights_off + - automation.kitchen_lights_on + - automation.kitchen_lights_toggle + - automation.kiosk_auto + - automation.kiosk_low_power + - automation.lightpack_effect + - automation.lightpack_select - automation.nightlight_off - automation.nightlight_on + - automation.scene_effect + - automation.video_player_resume + - automation.video_player_stop automations_modes: name: Modes Automations @@ -90,15 +107,19 @@ automations_modes: entities: - automation.low_power_mode_start - automation.low_power_mode_stop - - automation.quiet_mode_start - - automation.quiet_mode_stop + - automation.motion_detection_auto - automation.nap_mode_start - automation.nap_mode_stop - automation.night_mode_start - automation.night_mode_stop + - automation.quiet_mode_start + - automation.quiet_mode_stop + - automation.tamper_detection_start + - automation.tamper_detection_stop configuration_switches: name: Configuration Switches control: hidden entities: - switch.aeotec_zstick_disco_light + - script.tamper_reset diff --git a/groups/default.yaml b/groups/default.yaml index de33473..1b92b19 100644 --- a/groups/default.yaml +++ b/groups/default.yaml @@ -11,6 +11,8 @@ default_view: - group.public_transit - group.climate - group.actions + - group.security + - group.presence # @@ -21,6 +23,7 @@ actions: control: hidden entities: - script.wake_up + - input_select.scene - input_boolean.night_mode - input_boolean.nap_mode - input_boolean.quiet_mode @@ -36,8 +39,16 @@ climate: notifications: name: Notifications entities: + - persistent_notification.security - persistent_notification.humidity +now: + name: " " + entities: + - sensor.date_friendly + - sensor.time_friendly + - sensor.sun_state + public_transit: name: Public Transit entities: @@ -48,15 +59,23 @@ public_transit: - sensor.home_to_market_2_hour - sensor.home_to_market_3_hour +presence: + name: Presence + control: hidden + entities: + - device_tracker.cellphone_her + - device_tracker.cellphone_him + +security: + name: Security Status + control: hidden + entities: + - sensor.doors_status + - sensor.motion_status + - sensor.tamper_status + wallpaper: name: " " entities: - camera.bing_wallpaper - sensor.bing_wallpaper_info - -now: - name: " " - entities: - - sensor.date_friendly - - sensor.time_friendly - - sensor.sun_state diff --git a/groups/invisible.yaml b/groups/invisible.yaml new file mode 100644 index 0000000..9bc3c88 --- /dev/null +++ b/groups/invisible.yaml @@ -0,0 +1,44 @@ +# +# Invisible groups +# +# These are used in automations and scripts in order to reduce redundancy and +# ease maintenance. +# +bed_lights: + name: Bed Lights + entities: + - light.underbed + - light.headboard + +ceiling_lights: + name: Ceiling Lights + entities: + - light.bedroom + - light.middle + - light.lounge + +kitchen_lights: + name: Kitchen Lights + entities: + - light.countertop + - light.sink + - light.microwave + - light.island + +lifx_lights: + name: LIFX Lights + entities: + - light.lounge_lamp + - light.spotlight + - light.shower + +motion_sensors: + name: Motion sensors + entities: + - binary_sensor.kiosk_motion_auto + - binary_sensor.lounge_multisensor_sensor + +washroom_lights: + name: Washroom Lights + entities: + - light.shower diff --git a/groups/status.yaml b/groups/status.yaml index b9bda6d..aa792fe 100644 --- a/groups/status.yaml +++ b/groups/status.yaml @@ -19,6 +19,7 @@ status_view: battery: name: Battery Levels entities: + - sensor.kiosk_battery - sensor.front_door_sensor_battery - sensor.bedroom_multisensor_battery - sensor.lounge_multisensor_battery @@ -27,6 +28,7 @@ humidity: name: Humidity entities: - sensor.average_humidity + - sensor.hline_dashed - sensor.bedroom_humidity - sensor.lounge_humidity @@ -52,15 +54,16 @@ system: - sensor.uptime_friendly - sensor.uptime_host - sensor.cpu_temp - - sensor.cpu_used - - sensor.ram_used_percent - - sensor.disk_used_percent + - sensor.processor_use + - sensor.memory_use_percent + - sensor.disk_use_percent - sensor.database_size - - sensor.logfile_size + - sensor.log_size temperature: name: Temperature entities: - sensor.average_temperature + - sensor.hline_dashed - sensor.bedroom_temperature - sensor.lounge_temperature diff --git a/groups/switchboard.yaml b/groups/switchboard.yaml index e5a9714..0f8f15b 100644 --- a/groups/switchboard.yaml +++ b/groups/switchboard.yaml @@ -16,13 +16,6 @@ switchboard_view: # # Groups # -bed: - name: Bed - entities: - - input_select.bed_effect - - light.underbed - - light.headboard - bedroom: name: Bedroom entities: @@ -51,6 +44,12 @@ kitchen: - light.sink - light.microwave - light.island + - display.kiosk + - binary_sensor.kiosk_motion_auto + # - light.mqtt_countertop + # - light.mqtt_sink + # - light.mqtt_microwave + # - light.mqtt_island lounge: name: Lounge @@ -58,13 +57,16 @@ lounge: - input_select.aurora_effect - light.aurora - sensor.hline_dashed - - light.spotlight + - input_select.lightpack_effect - light.lightpack + - sensor.hline_dashed_2 + - light.spotlight - switch.souvenirs_light - switch.window_light - sensor.lounge_temperature - sensor.lounge_humidity - sensor.lounge_luminance + - binary_sensor.lounge_multisensor_sensor washroom: name: Washroom diff --git a/groups/weather.yaml b/groups/weather.yaml index fb55598..cb356b9 100644 --- a/groups/weather.yaml +++ b/groups/weather.yaml @@ -28,6 +28,7 @@ atmospheric_safety: - sensor.aqi_ozone_friendly - sensor.aqi_carbon_monoxide_friendly - sensor.aqi_nitrogen_dioxide_friendly + - sensor.aqi_sulphur_dioxide_friendly radar_rain: name: Rain Radar Map diff --git a/gtfs/.gitkeep b/gtfs/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/gtfs/README.md b/gtfs/README.md index 45d2eb1..ad11da3 100644 --- a/gtfs/README.md +++ b/gtfs/README.md @@ -2,6 +2,18 @@ GTFS data serves to calculate public transit routes and times. The [GTFS](https://home-assistant.io/components/sensor.gtfs/) sensor indicates how to convert new feeds into a database for local queries. +
+
+
+ Public Transit group + Public Transit group (dark theme) +
+
+

Public Transit group with schedules for the next three departures in two directions. Yellow (warning) and red (critical) highlights are using /theme cards defined in /customize.yaml based on how much time is left before the bus leaves. 🚌🏃

+
+
+
+ ## A slow sensor @@ -21,30 +33,42 @@ The way to regain speed is to add missing indexes and delete all schedule data f Ideally do perform the following steps on a better machine, like a Docker build of Home Assistant on your desktop computer. Mind you, you could still use a Raspberry Pi but it will just take longer to do all those steps and it will bore you to death. 1. Build the database. Let Home Assistant complain all it wants and wait for the database to stop growing, your sign that it is ready. -1. Connect to the resulting SQLite database via the command-line and create a backup, just in case: +2. Connect to the resulting SQLite database via the command-line and create a backup, just in case: ```sql - .backup backup_full.sqlite - ``` -1. Then run the following commands to delete all stops data except the few that you have configured for the sensor (say, 3333, 4444 and 5555): + .backup backup_full.sqlite + ``` +3. Then run the following commands to delete all stops data except the few that you have configured for the sensor (say, 3333, 4444 and 5555): ```sql - DELETE FROM stop_times WHERE stop_id NOT IN (3333, 4444, 5555); - DELETE FROM stops WHERE stop_id NOT IN (3333, 4444, 5555); + DELETE FROM stop_times + WHERE stop_id NOT IN (3333, 4444, 5555); + + DELETE FROM stops + WHERE stop_id NOT IN (3333, 4444, 5555); ``` -1. While still connected, add the missing undexes: +4. While still connected, add the missing undexes: ```sql - CREATE INDEX idx_trips_service_id ON trips(service_id); - CREATE INDEX idx_stop_times_stop_id ON stop_times(stop_id); - CREATE INDEX idx_stop_times_trip_id ON stop_times(trip_id); - CREATE INDEX idx_stop_times_stop_sequence ON stop_times(stop_sequence); - CREATE INDEX idx_stop_times_departure_time ON stop_times(departure_time); + CREATE INDEX idx_trips_service_id ON trips(service_id); + + CREATE INDEX idx_stop_times_stop_id ON stop_times(stop_id); + + CREATE INDEX idx_stop_times_trip_id ON stop_times(trip_id); + + CREATE INDEX idx_stop_times_stop_sequence ON stop_times(stop_sequence); + + CREATE INDEX idx_stop_times_departure_time ON stop_times(departure_time); ``` -1. In my case my transit agency did not add its own agency ID to the routes, leading to faulty queries. To fix this: +5. In my case my transit agency did not add its own agency ID to the routes, leading to faulty queries. To fix this: ```sql - UPDATE routes SET agency_id = (SELECT agency_id FROM agency WHERE feed_id = 1); + UPDATE routes + SET agency_id = ( + SELECT agency_id + FROM agency + WHERE feed_id = 1 + ); ``` -1. Finally, trim the database file to remove all the empty space within. +6. Finally, trim the database file to remove all the empty space within. ```sql - VACUUM; + VACUUM; ``` Voilà! The resulting file can be copied over to the Raspberry Pi and Home Assistant restarted. Speed at last! diff --git a/lights/README.md b/lights/README.md index 7bdec22..c47d12c 100644 --- a/lights/README.md +++ b/lights/README.md @@ -2,7 +2,7 @@ ## LIFX smart Wi-Fi lights -LIFX devices are directly controlled by WiWi-FiFi, so no bridges are needed. The devices are first setup via the [LIFX app](https://www.lifx.com/pages/go) where their names are set. For increased stability they then have static IP addresses assigned in the router. +LIFX devices are directly controlled by Wi-Fi, so no bridges are needed. The devices are first setup via the [LIFX app](https://www.lifx.com/pages/go) where their names are set. For increased stability they then have static IP addresses assigned in the router. ### LIFX+ A19 RGBW light bulbs @@ -16,28 +16,50 @@ These **[LIFX+ A19 RGBW](https://www.lifx.com/products/lifx-plus)** Homekit-comp They do have couple of minor annoyances however: - They're expensive. Seriously, $100 CAD **each**? Better wait for a special. -- There have a slight high-pitch noise. While it feels more noticeable in higher-frequency brightness levels, it occurs more or less randomly. Some of my light fixtures increased this noise, so I only use these bulbs where I cannot hear them regularly. -- They sometimes drop off the network for a few seconds, despite having static IP addresses assigned. Not cool. +- They sometimes drop off the network for a few seconds, despite having static IP addresses assigned. Not fun. +- There have a slight high-pitch noise. Think old-school power adapter or CRT television high-pitch, but louder. While it feels more noticeable in higher-frequency brightness levels, it occurs more or less randomly when changing their brightness or turning them on. Some of my light fixtures increased this noise, so I only use these bulbs where I cannot hear them regularly, which is a shame. If you have tinitus, this isn't the kind of background noise you want to have. 🤪 -I have their white colour gradually shift from daylight to warm white with varying intensity based on the time of day in [`/automations/cct.yaml`](../automations/cct.yaml). They also serve as nightlights through [`/automations/nightlight_on.yaml`](../automations/nightlight_on.yaml), IR illuminators and for some alerts like [`/automations/front_door_opened.yaml`](../automations/front_door_opened.yaml). +
+
+
+ LIFX+ card +
+
+

LIFX light control.

+
+
+
+ +I have their white colour gradually shift from daylight to warm white with varying intensity based on the time of day in [`/automations/cct_lifx.yaml`](../automations/cct_lifx.yaml). They also serve as nightlights through [`/automations/nightlight_on.yaml`](../automations/nightlight_on.yaml), IR illuminators and for some alerts like [`/automations/front_door_opened.yaml`](../automations/front_door_opened.yaml). ### LIFX Z RGBW LED strips **[LIFX Z RGBW strips](https://www.lifx.com/products/lifx-z)** are used as ceiling wash lights and bed underglow lights. These are not the newer HomeKit versions, but the non-HomeKit 3-meters versions were on clearance! Each kit comes with 1-meter strips, and up to 10 strips can be used per 24v 3A controller. Still a bit pricier than DIY solutions, but the design simplicity, time savings, UL-rating and clearance price make this a no-brainer. Plus they look better and brighter than HUE strips thanks to the added white LEDs! +
+
+
+ LIFX Z ceiling group +
+
+

LIFX Z strip control.

+
+
+
+ To make the ceiling strips glow prettily in unison: 1. First, ceiling strips are organized in a dedicated group using the LIFX app. -1. Then [cloud-based scenes](https://home-assistant.io/components/scene.lifx_cloud/) are defined with the LIFX app and applied to a this ceiling group. -1. Afterwards the scenes' UUID are manually retrieved [via the API](https://api.developer.lifx.com/docs/list-scenes). -1. These scenes UUID are copied over to [`/automations/ceiling_effect.yaml`](../automations/ceiling_effect.yaml). -1. Scenes can then either be changed manually using an **input_select** with [`/automations/ceiling_select.yaml`](../automations/ceiling_select.yaml) or automatically throughout the day with [`/automations/ceiling_schedule.yaml`](../automations/ceiling_schedule.yaml). -1. Finally, to make them extra special, the LIFX app is used to apply a slow motion effect to each LED strip, so that colors gradually move/fade along the strips. So pretty! :-) +2. Then [cloud-based scenes](https://home-assistant.io/components/scene.lifx_cloud/) are defined with the LIFX app and applied to a this ceiling group. +3. Afterwards the scenes' UUID are manually retrieved [via the API](https://api.developer.lifx.com/docs/list-scenes). +4. These scenes UUID are copied over to [`/automations/ceiling_effect.yaml`](../automations/ceiling_effect.yaml). +5. Scenes can then either be changed manually using an **input_select** with [`/automations/ceiling_select.yaml`](../automations/ceiling_select.yaml) or automatically throughout the day with [`/automations/ceiling_schedule.yaml`](../automations/ceiling_schedule.yaml). +6. Finally, to make them extra special, the LIFX app is used to apply a slow motion effect to each LED strip, so that colors gradually move/fade along the strips. So pretty! :-) Same goes for the bed underglow lights. This setup works well, but the strips themselves are a bit buggy even before being used with Home Assistant: -- Sometimes the motion stops in one or more strips. I have to use the LIFX app to kick them back into motion. +- Sometimes the motion stops in one, more or all strips. I have to use the LIFX app to kick them back into motion. It happens daily, which is a bummer. 😒 - Other times a LIFX cloud scene itself is deemed to have a motion programmed, so one strip will get two motion commands applied resulting in a slight stuttering effect. Once again I use the LIFX app, this time to remove the motion from the scene. @@ -47,6 +69,17 @@ The original [Lightpack](https://store.lightpack.tv) is a lighting device placed For my HTPC I use a 100-LEDs DIY build of the [Adalight](https://learn.adafruit.com/adalight-diy-ambient-tv-lighting) ambient TV light project by Adafruit that I crafted years ago. This Adalight device is also compatible with Prismatik. The open source software's development was halted a while back however, but [a kind soul has since forked the project](https://github.com/psieg/Lightpack) and keeps on improving it. +
+
+
+ Lightpack card +
+
+

Lightpack control.

+
+
+
+ To allow [the third-party component](https://github.com/kklemm91/Lightpack-HASS) [`/custom_components/light/lightpack.yaml`](../custom_components/light/lightpack.yaml) to communicate with your Lightpack device, one has to enable the sockets API in Prismatik and optionally add a password. If your IoT LAN is segregated from your TV-connected computer you will also have to play with your firewall rules. @@ -54,32 +87,68 @@ To allow [the third-party component](https://github.com/kklemm91/Lightpack-HASS) [LimitlessLED](http://www.limitlessled.com) manufactures LED controllers and devices for many brands, including the popular and affortable [MiLight](http://www.milight.com) devices found on [AliExpress](https://www.aliexpress.com/wholesale?SearchText=milight) and [eBay](https://www.ebay.ca/sch/i.html?_nkw=milight). -The 12v-24v LED controllers receive their commands via a [proprietary RF protocol](http://blog.christophermullins.com/2017/03/18/reverse-engineering-the-new-milightlimitlessled-2-4-ghz-protocol), either through a remote/control panel or through a Wifi bridge. They do not however report back their state, which means that if the light is toggled or modulated by the manufacturer's app, then these changes will not be reflected in Home Assistant and vice versa. Annoying, but hey they are cheap! +The 12v-24v LED controllers receive their commands via a [proprietary RF protocol](http://blog.christophermullins.com/2017/03/18/reverse-engineering-the-new-milightlimitlessled-2-4-ghz-protocol), either through a remote/control panel or through a Wifi bridge. They do not however report back their state, which means that if the light is toggled or modulated by the manufacturer's app, then these changes will not be reflected in Home Assistant and vice versa. Annoying, but hey they are cheap and ubiquitous! + +In this case I use a USB-powered [MiLight iBox2 Wifi bridge](http://www.limitlessled.com/shop/wifi-bridge-v6/) to send signals to four [FUT035 CCT controllers](https://www.futlight.com/productdetails.aspx?id=293&typeid=146), each in their own group, that are connected to custom-cut UL-Listed [high-CRI CCT LED strips](http://ledmontreal.com/en/led-strips-without-accessories/24v-led-strips-without-accessories/cct-adjustable-led-strip.html) encased in [light diffusing aluminum profiles](http://ledmontreal.com/en/led-bars-and-profiles-led-montreal/continuous-lighting-aluminum-profile.html) and placed in various locations in the kitchen. 24v DC power is provided by UL-Listed [plug-in and hard-wired adapters](http://ledmontreal.com/en/12v-24v-power-supplies/24v-power-supplies/). While the controllers are CCT, they respond to the newer RGB-CCT signals instead of the older CCT ones, so the FUT035 are paired to the MiLight Bridge using a RGB-CCT virtual remote in MiLight's mobile app. + +Aside from regular automations, the lights are controlled physically via a [Flic smart button](https://flic.io): one click turns them on or off, double-click toggles some of them, and hold set thems to full brightness. -In this case I use a USB-powered [MiLight iBox2 Wifi bridge](http://www.limitlessled.com/shop/wifi-bridge-v6/) to send signals to four [FUT035 CCT controllers](https://www.futlight.com/productdetails.aspx?id=293&typeid=146), each in their own group, that are connected to custom-cut UL-Listed [high-CRI CCT LED strips](http://ledmontreal.com/en/led-strips-without-accessories/24v-led-strips-without-accessories/cct-adjustable-led-strip.html) encased in [light diffusing aluminum profiles](http://ledmontreal.com/en/led-bars-and-profiles-led-montreal/continuous-lighting-aluminum-profile.html) and placed in various locations in the kitchen. 24v DC power is provided by UL-Listed [plug-in and hard-wired adapters](http://ledmontreal.com/en/12v-24v-power-supplies/24v-power-supplies/). +
+
+
+ LimitlessLED card +
+
+

LimitlessLED control.

+
+
+
-The lights are controlled via a [Flic smart button](https://flic.io). Their white colour slowly changes from daylight to warm white depending on the time of day, and their brightness is also gradually altered on a schedule. These changes are subtle but noticeable, since the controllers only have limited precision. +Their white colour slowly changes from daylight to warm white depending on the time of day with [`/automations/cct_limitlessled.yaml`](../automations/cct_limitlessled.yaml), and their brightness is also gradually altered on a schedule. At night, they serve as nightlights with [`/automations/nightlight_on.yaml`](../automations/nightlight_on.yaml). + +In retrospec, while this setup works I do have reservations. Should I find a better controller solution I will switch away from LimilessLED/MiLight products: +- The iBox2 bridge does not report on the light states, so if I restart Home Assistant while the lights are on or use the MiLight app to make changes, Home Assistant will loose track of the real states. +- The controllers make the light strips flicker when dimmed, more so than any equally dimmed LIFX, Philips, Feit Electric and GE LED bulbs that I own. Not noticeable from straight on, a tiny bit noticeable with peripheral vision, and definitely a lot when using a video camera or Viso System's [Flicker tester app]('http://www.visosystems.com/products/flicker-tester/') it. +- When connecting energized UL-listed DC adapters in the controllers' barrel plug, I get starks flying out of the FUT035. 💥 Every time. And you do have to physically plug/unplug power them to link them to the bridge and to debug the connection. Such a lack of power regulation is not cool. 😠 + +As an alternative to using the MiLight bridge with its limit of four groups, [Chris Mullins has done a kick-ass job](http://blog.christophermullins.com/2017/02/11/milight-wifi-gateway-emulator-on-an-esp8266/) of reverse-engineering the MiLighs protocols and explains how to easily assemble a DIY bridge using [his open-source project](https://github.com/sidoh/esp8266_milight_hub) to allow you to control as many groups as you want, using MQTT too if you wish. All you'll need is an [ESP8266 wifi module](https://en.wikipedia.org/wiki/ESP8266), a [nRF24L01+ transceiver](https://hackaday.com/2015/02/23/nordic-nrf24l01-real-vs-fake/) and some prototyping wire, under about $20. I have built one using a [NodeMCU 1.0](https://frightanic.com/iot/comparison-of-esp8266-nodemcu-development-boards/#v1), and will switch to it when the need to add more MiLight groups arises ...unless I find a better solution to replace all of these MiLight controllers with. ## Nanoleaf Aurora smart light panels -What an awesome decorative lighting kit! Makes any place feel like a sophisticated café or designer cocktail bar. +What an awesome decorative lighting kit! Makes any place feel like a sophisticated café or designer cocktail bar. 😍 The [Aurora](https://nanoleaf.me) is managed directly through WiFi, so no need for a hub, and is HomeKit compatible. It is integrated into Home Assistant through a third party component in [`/custom_components/light/aurora.yaml`](../custom_components/light/aurora.yaml) (actually, I am using this forked version compatible with Hass.io) Like with the LIFX Z light strips, I have scheduled different effects and brightness levels in Home Assistant so that my Aurora changes looks throughout the day. The interface is the same as above, also with a manual override should I prefer a specific effect. The effects do not reside in the cloud however, but directly on the device itself which is nice. +
+
+
+ Nanoleaf Aurora card +
+
+

Nanoleaf Aurora control.

+
+
+
+ To program the Aurora: 1. First set up the kit using the [Nanoleaf App](https://nanoleaf.me/en-ca/consumer-led-lighting/products/smarter-series/nanoleaf-cloud/nanoleaf-smarter-series-app/). 1. Through the app, download or create a few effects and give them memorable names. -1. Copy the names into to [`/automations/aurora_effect.yaml`](../automations/aurora_effect.yaml). +1. Copy the names into [`/automations/aurora_effect.yaml`](../automations/aurora_effect.yaml). 1. Effects will change automatically throughout the day with [`/automations/aurora_schedule.yaml`](../automations/aurora_schedule.yaml), which an be overridden manually using an **input_select** connected to [`/automations/aurora_select.yaml`](../automations/aurora_select.yaml) -Instant class! +Instant class! 🍸 + +While a great Canadian product 🇨🇦, it does have very minor drawbacks: +- Installation using either their nails or 3M Command strips (which I used), which isn't seamless. +- They are **very bright**, like those showroom TV sets that are programmed to make the image pop even in a fully lit store, so I run my 9-panels unit at 50% max brightness which makes the stepping brightness changes more noticeable. They would definitely pop in a sunlit environment though, which is cool. +- Buying your first set will make you want to buy more of them. A lot more. It's a bit like crack, but good for you. 😃 ## Customization The bulk of the customization is done in [`/customize.yaml`](../customize.yaml) and [`/customize_glob.yaml`](../customize_glob.yaml). -The looks of the light state cards depend on Custom UI and other templates in [`/www/custom_ui`](../www/custom_ui). +The looks of the light state cards depend on Custom UI and other templates in [`/www/custom_ui/`](../www/custom_ui). diff --git a/lights/lifx.yaml b/lights/lifx.yaml index 12bea68..81756b9 100644 --- a/lights/lifx.yaml +++ b/lights/lifx.yaml @@ -3,7 +3,7 @@ # # All devices are discovered by the platform, so no need to manage them here. # -# @see /automations/cct.yaml +# @see /automations/cct_lifx.yaml # @see /automations/bed_effect.yaml # @see /automations/bed_schedule.yaml # @see /automations/ceiling_effect.yaml diff --git a/lights/lightpack.yaml b/lights/lightpack.yaml index 2aa5a4d..92da6b7 100644 --- a/lights/lightpack.yaml +++ b/lights/lightpack.yaml @@ -5,9 +5,9 @@ # # @see /custom_components/light/lightpack.yaml # -# @link https://learn.adafruit.com/adalight-diy-ambient-tv-lighting -# @link https://github.com/psieg/Lightpack # @link https://github.com/kklemm91/Lightpack-HASS +# @link https://github.com/psieg/Lightpack +# @link https://learn.adafruit.com/adalight-diy-ambient-tv-lighting # - platform: lightpack name: Lightpack diff --git a/lights/limitlessled.yaml b/lights/limitlessled.yaml index a6fa7b3..f99a92d 100644 --- a/lights/limitlessled.yaml +++ b/lights/limitlessled.yaml @@ -1,32 +1,93 @@ # # LimitlessLED smart light for MiLight devices # -# @see /automations/cct.yaml +# The MiLights led strips controllers I use are the FUT035 for white-temperature +# control only (for use with high-CRI CCT LED strips where workarea white light +# primes over colourfulness). However, these controllers do not respond reliably +# to the "cct" device type, which uses an older inaccurate protocol for legacy +# CCT lights. Instead, the FUT035 controllers have to use the newer "rgbww" +# device type, even if they do not provide RGB outputs. This setting then works +# reliably, even if the frontend UI offers extra colour options that aren't +# relevant for white-only devices. +# +# @see /automations/cct-limitlessled.yaml # # @link http://www.limitlessled.com/ +# @link http://www.milight.com/milight-wifi-box/ # @link https://www.futlight.com/productdetails.aspx?id=293&typeid=146 # @link https://www.futlight.com/productdetails.aspx?id=239&typeid=125 -# @link http://www.milight.com/milight-wifi-box/ # @link https://home-assistant.io/components/light.limitlessled/ # - platform: limitlessled bridges: - - host: !secret limitleddled_bridge_host - port: !secret limitleddled_bridge_port + - host: !secret limitlessled_bridge_host + port: !secret limitlessled_bridge_port groups: - - number: 4 - type: white - name: Island - fade: on - number: 1 - type: white - name: Countertop + name: Sink + type: rgbww fade: on - number: 2 - type: white - name: Sink + name: Countertop + type: rgbww fade: on - number: 3 - type: white name: Microwave + type: rgbww fade: on + - number: 4 + name: Island + type: rgbww + fade: on + + +# +# Milight Hub emulator +# +# Controls MiLight devices using a DIY gateway emulator via MQTT. For +# prototyping purposes. +# Hardware device is an ESP8266 (NodeMCU 1.0 module) connected to a nRF24L01+ +# transceiver and running custom firmware by Chris Mullins. +# +# MQTT topic formats: +# commands: milight/commands/:device_id/:device_type/:group_id +# states: milight/states/:device_id/:device_type/:group_id +# Placeholders: +# :device_id = MiLight bridge ID linked to a device. +# :device_type = Type of light controlled, based on compatible remote. +# :group_id = Group a light is assigned to. +# +# @link https://github.com/sidoh/esp8266_milight_hub +# @link http://blog.christophermullins.com/2017/02/11/milight-wifi-gateway-emulator-on-an-esp8266/ +# +# - platform: mqtt_json +# name: MQTT Sink +# command_topic: milight/commands/0xCAFE/rgb_cct/1 +# state_topic: milight/states/0xCAFE/rgb_cct/1 +# qos: 2 +# color_temp: true +# brightness: true + +# - platform: mqtt_json +# name: MQTT Countertop +# command_topic: milight/commands/0xCAFE/rgb_cct/2 +# state_topic: milight/states/0xCAFE/rgb_cct/2 +# qos: 2 +# color_temp: true +# brightness: true + +# - platform: mqtt_json +# name: MQTT Microwave +# command_topic: milight/commands/0xCAFE/rgb_cct/3 +# state_topic: milight/states/0xCAFE/rgb_cct/3 +# qos: 2 +# color_temp: true +# brightness: true + +# - platform: mqtt_json +# name: MQTT Island +# command_topic: milight/commands/0xCAFE/rgb_cct/4 +# state_topic: milight/states/0xCAFE/rgb_cct/4 +# qos: 2 +# color_temp: true +# brightness: true diff --git a/misc/README.md b/misc/README.md index 105c9ea..505017c 100644 --- a/misc/README.md +++ b/misc/README.md @@ -1,10 +1,60 @@ # Miscellaneous -This folder gathers all simpler configuration: - -- [`binary_sensors.yaml`](binary_sensors.yaml): Flic buttons. -- [`input_booleans.yaml`](input_booleans.yaml): Modes and other intermediary state holder for [`/automations`](../automations). -- [`input_selects.yaml`](input_selects.yaml): List of light effects for the frontend. -- [`media_players.yaml`](media_players.yaml): Kodi and Plex. -- [`shell_commands.yaml`](shell_commands.yaml): Reusable command-line directives when no component exists or provides these options. -- [`variables.yaml`](variables.yaml): Intermediary data holder for [`/automations`](../automations). +This folder gathers all simpler configuration files. + + +## Inputs + +These are essentially used as triggers and conditions for [`/automations/`](../automations). + + +### [`✅ ./input_booleans.yaml`](input_booleans.yaml) + +Modes and other binary intermediary state holders for [`/automations/`](../automations). + + +### [`🔲 ./input_selects.yaml`](input_selects.yaml) + +List of light effects and global scenes for the frontend and for [`/appdaemon/dashboards/`](../appdaemon/dashboards). + + +### [`❓ ./variables.yaml`](variables.yaml) + +Flexible intermediary data holder, using the [third-party](https://github.com/rogro82/hass-variables) [`/custom_components/varyable.py`](../custom_components/varyable.py). + + +## Other + +### [`🔘 ./binary_sensors.yaml`](binary_sensors.yaml) + +Essentially used for [Flic buttons](https://flic.io) and [Fully Kiosk Browser](https://www.ozerov.de/fully-kiosk-browser) motion sensor. + + +### [`📍 ./device_trackers.yaml`](device_trackers.yaml) + +For tracking device presence with Bluetooth and [UniFi](https://www.ubnt.com/unifi/unifi-cloud-key/) wireless access point. + + +### [`🎦 ./displays.yaml`](displays.yaml) + +To enable basic control of the [Fully Kiosk Browser](https://www.ozerov.de/fully-kiosk-browser) using the [third-party](https://github.com/daemondazz/homeassistant-displays) [`/custom_components/display/`](../custom_components/display) component. + + +### [`📽 ./media_players.yaml`](media_players.yaml) + +For [Kodi](https://kodi.tv) and [Plex](https://www.plex.tv). + + +### [`🌈 ./scenes.yaml`](scenes.yaml) + +Simple registration for [LIFX's server-based scenes](https://www.lifx.com/pages/themes-scenes), see [`/lights/`](../lights#lifx-smart-wi-fi-lights) for more details. All other scenes are implemented as [`/scripts/`](../scripts) in order to access more advanced features. + + +### [`🐚 ./shell_commands.yaml`](shell_commands.yaml) + +Reusable command-line directives when no component exists or provides these options reliably. + + +### [`🗺 ./zones.yaml`](zones.yaml) + +Used for presence tracking and automations based on user distance from key locations. diff --git a/misc/binary_sensors.yaml b/misc/binary_sensors.yaml index 2728685..501fec7 100644 --- a/misc/binary_sensors.yaml +++ b/misc/binary_sensors.yaml @@ -1,3 +1,10 @@ +# +# Binary sensors +# +# @link https://home-assistant.io/components/binary_sensor/ +# + + # # Flic smart button # @@ -12,3 +19,38 @@ port: !secret flic_port discovery: true timeout: 3 + + +# +# Fully Kiosk Browser motion sensor +# +# The Fully app can only send "onMotion" events as it is stateless. Instead of +# coming up with a complicated yet fragile Javascript state-handler that would +# calculate the last time any motion was detected and then send an "off" signal +# and would survive across URL changes (but would fail if the Android device is +# offline or if the app is forced-closed), an extra server-side sensor is much +# sturdier, if a bit less accurate. It should turn off within 3-4 minutes after +# the last change. +# +# The "binary_sensor.kiosk_motion" is dynamically created by the first +# "onMotion" event call for a custom Javascript declared in all dashboards using +# the "Modern" theme.. Two API calls are done sequentially, one to turn off the +# binary sensor, then other to turn it right back on. This way the sensor state +# is guaranteed to change, and the "last_changed" and "last_updated" timestamps +# along with it. +# +# @see /appdaemon/custom_css/modern/variables.yaml +# +- platform: template + sensors: + kiosk_motion_auto: + friendly_name: Kiosk Motion + device_class: motion + entity_id: + - sensor.time + - binary_sensor.kiosk_motion + delay_off: + seconds: 5 + value_template: >- + {{ is_state('binary_sensor.kiosk_motion', 'on') + and (180 >= as_timestamp(now()) - as_timestamp(states.binary_sensor.kiosk_motion.last_changed)) }} diff --git a/misc/device_trackers.yaml b/misc/device_trackers.yaml index dc7a7ea..82eb0a1 100644 --- a/misc/device_trackers.yaml +++ b/misc/device_trackers.yaml @@ -1,14 +1,24 @@ # -# Owntracks +# Device trackers # -# @link https://home-assistant.io/components/device_tracker.owntracks/ +# @link https://home-assistant.io/components/device_tracker/ # -- platform: owntracks + + +# +# Bluetooth +# +# https://home-assistant.io/components/device_tracker.bluetooth_tracker/ +# +- platform: bluetooth_tracker # # Ubiquiti Unifi wireless access point # +# Connects to the UniFi controller with a read-only user. +# +# @link https://www.ubnt.com/unifi/unifi-cloud-key/ # @link https://home-assistant.io/components/device_tracker.unifi/ # - platform: unifi @@ -17,6 +27,6 @@ username: !secret unifi_username password: !secret unifi_password verify_ssl: false - track_new_devices: false + track_new_devices: true interval_seconds: 10 consider_home: 180 diff --git a/misc/displays.yaml b/misc/displays.yaml new file mode 100644 index 0000000..e6a6c6b --- /dev/null +++ b/misc/displays.yaml @@ -0,0 +1,29 @@ +# +# Displays +# +# @see /custom_components/display/ +# +# @link https://github.com/daemondazz/homeassistant-displays +# + + +# +# Fully Kiosk Browser app +# +# Third-party component to get some basic information on an instance of the +# Fully app running on a connected Android device and to allow the toggling of +# its screen. +# +# Motion sensor is not integrated here, but instead is an API endpoint called +# by a custom JavaScript handler in the Moden HADashboard theme. +# +# @see /custom_components/display/fully_kiosk.py +# @see /appdaemon/custom_css/modern/variables.yaml +# +# @link https://www.ozerov.de/fully-kiosk-browser/#rest +# +- platform: fully_kiosk + name: Kiosk + host: !secret fully_kiosk_host + port: !secret fully_kiosk_port + password: !secret fully_kiosk_password diff --git a/misc/homekit.yaml b/misc/homekit.yaml new file mode 100644 index 0000000..762da6d --- /dev/null +++ b/misc/homekit.yaml @@ -0,0 +1,30 @@ +auto_start: true +port: !secret homekit_port +filter: + include_entities: + - input_boolean.low_mode + - input_boolean.nap_mode + - input_boolean.night_mode + - input_boolean.quiet_mode + - light.bedroom + - light.countertop + - light.headboard + - light.island + - light.lightpack + - light.lounge + - light.microwave + - light.middle + - light.sink + - light.underbed + - sensor.average_humidity + - sensor.average_temperature + - sensor.bedroom_humidity + - sensor.bedroom_temperature + - sensor.lounge_humidity + - sensor.lounge_temperature + - switch.bedroom_fan + - switch.bedside_light + - switch.dehumidifier + - switch.nightstand_light + - switch.souvenirs_light + - switch.window_light diff --git a/misc/input_booleans.yaml b/misc/input_booleans.yaml index 08c9c69..07aa144 100644 --- a/misc/input_booleans.yaml +++ b/misc/input_booleans.yaml @@ -1,58 +1,57 @@ +# +# Input booleans +# +# @link https://home-assistant.io/components/input_boolean/ +# + + # # Modes # low_mode: name: Low power mode - initial: off + icon: mdi:weather-sunset-down nap_mode: name: Nap mode - initial: off + icon: mdi:sleep night_mode: name: Night mode - initial: off + icon: mdi:weather-night quiet_mode: name: Quiet mode - initial: off + icon: mdi:volume-mute scene_mode: name: Scene mode - initial: off + icon: mdi:looks # # Manual effect overrides # -aurora_effect_override: - name: Aurora has overriding effect set - initial: off - -bed_effect_override: - name: Bed underglow lights have overriding effect set - initial: off - -ceiling_effect_override: - name: Ceiling wash lights have overriding effect set - initial: off +kitchen_lights_override: + name: Kitchen Lights have overriding effect set + icon: mdi:food-fork-drink # -# Permimiter seal +# Security # doors_open: name: Doors are open - initial: off + icon: mdi:door-open -windows_open: - name: Windows are open - initial: off +motion_detected: + name: Motion detected + icon: mdi:run +tamper_detected: + name: Tamper detected + icon: mdi:security-home -# -# Miscellaneous -# -update_available: - name: Update available - initial: off +windows_open: + name: Windows are open + icon: mdi:window-open diff --git a/misc/input_selects.yaml b/misc/input_selects.yaml index e40920f..48b0d19 100644 --- a/misc/input_selects.yaml +++ b/misc/input_selects.yaml @@ -1,3 +1,10 @@ +# +# Lists of selectable values +# +# @link https://home-assistant.io/components/input_select/ +# + + # # Nanoleaf Aurora effects # @@ -6,7 +13,7 @@ # aurora_effect: name: Aurora Effect - icon: mdi:star + icon: mdi:vector-triangle initial: Auto options: - Auto @@ -94,3 +101,40 @@ ceiling_effect: - Soothing - Tranquil - Warming + + +# +# Lightpack effect +# +# @see /automations/lightpack_effect.yaml +# @see /automations/lightpack_select.yaml +# +lightpack_effect: + name: Lightpack Effect + icon: mdi:tv + initial: Default + options: + - Default + - Daylight + - Gaming + - Movie + - Party + - Romantic + + +# +# Scene +# +# @see /automations/scene_select.yaml +# @see /misc/input_boolean +# +scene: + name: Scene + icon: mdi:star + # initial: Default + options: + - Default + - Daylight + - Gaming + - Movie + - Romantic diff --git a/misc/media_players.yaml b/misc/media_players.yaml index e663947..7cad8b5 100644 --- a/misc/media_players.yaml +++ b/misc/media_players.yaml @@ -1,3 +1,10 @@ +# +# Media players +# +# @link https://home-assistant.io/components/media_player/ +# + + # # Kodi # @@ -17,15 +24,14 @@ # # Plex # -# Todo: Investigate the buggy connection to this media player. -# # @link https://www.plex.tv/ # @link https://home-assistant.io/components/media_player.plex/ # -# - platform: plex -# name: Plex -# include_non_clients: true -# scan_interval: 5 -# show_all_controls: false -# use_custom_entity_ids: false -# use_episode_art: true +- platform: plex + name: Plex + entity_namespace: plex + include_non_clients: true + scan_interval: 5 + show_all_controls: false + use_custom_entity_ids: false + use_episode_art: true diff --git a/misc/recorder.yaml b/misc/recorder.yaml new file mode 100644 index 0000000..88b465f --- /dev/null +++ b/misc/recorder.yaml @@ -0,0 +1,41 @@ +purge_interval: 2 +purge_keep_days: 5 +exclude: + domains: + - camera + - group + - light + - scene + - script + - sensor + - sun + - updater + - zone + - zwave + entities: + - switch.aeotec_zstick_disco_light +include: + entities: + - sensor.aqi + - sensor.aqi_carbon_monoxide + - sensor.aqi_carbon_monoxide_friendly + - sensor.aqi_friendly + - sensor.aqi_nitrogen_dioxide + - sensor.aqi_nitrogen_dioxide_friendly + - sensor.aqi_ozone + - sensor.aqi_ozone_friendly + - sensor.aqi_particles + - sensor.aqi_particles_friendly + - sensor.average_humidity + - sensor.average_humidity_friendly + - sensor.average_temperature + - sensor.bedroom_humidity + - sensor.bedroom_temperature + - sensor.lounge_humidity + - sensor.lounge_luminance + - sensor.lounge_temperature + - sensor.outside_humidity + - sensor.outside_temperature + - sensor.uv + - sensor.uv_friendly + - sensor.wind_speed diff --git a/scenes/lifx_cloud.yaml b/misc/scenes.yaml similarity index 77% rename from scenes/lifx_cloud.yaml rename to misc/scenes.yaml index 7f48873..8214a3d 100644 --- a/scenes/lifx_cloud.yaml +++ b/misc/scenes.yaml @@ -1,3 +1,10 @@ +# +# Scenes +# +# @link https://home-assistant.io/components/scene/ +# + + # # LIFX cloud scenes # diff --git a/misc/shell_commands.yaml b/misc/shell_commands.yaml index de154c8..55ab98e 100644 --- a/misc/shell_commands.yaml +++ b/misc/shell_commands.yaml @@ -1,3 +1,18 @@ +# +# Shell commands +# +# @link https://home-assistant.io/components/shell_command/ +# + + +# +# Fully Kiosk Browser brightness +# +# @link https://www.ozerov.de/fully-kiosk-browser/#rest +# +kiosk_brightness: 'curl -k "http://{{host}}:{{port}}/?cmd=setStringSetting&key=screenBrightness&value={{value}}&type=json&password={{password}}"' + + # # LIFX API command to apply a cloud scene # diff --git a/misc/variables.yaml b/misc/variables.yaml index d7a376a..4f96e0e 100644 --- a/misc/variables.yaml +++ b/misc/variables.yaml @@ -1,3 +1,12 @@ +# +# Variables +# +# @see /custom_components/varyable.py +# +# @link https://github.com/rogro82/hass-variables +# + + # # Nanoleaf Aurora effect and brightness # @@ -28,3 +37,18 @@ ceiling_effect: restore: true attributes: uuid: '' + + +# +# Lightpack effect +# +lightpack_effect: + value: False + restore: true + + +# +# Perimeter tamper detection +tamper_detected: + value: False + restore: False diff --git a/misc/zones.yaml b/misc/zones.yaml new file mode 100644 index 0000000..01ff6ec --- /dev/null +++ b/misc/zones.yaml @@ -0,0 +1,35 @@ +# +# Zones +# +# @link https://home-assistant.io/components/zone/ +# + + +# +# Home zone +# +- name: Home + latitude: !secret zone_home_latitude + longitude: !secret zone_home_longitude + radius: 100 + icon: mdi:home-heart + + +# +# Bus terminal zone +# +- name: Bus Terminal + latitude: !secret zone_terminal_latitude + longitude: !secret zone_terminal_longitude + radius: 500 + icon: mdi:subway + + +# +# Work zone +# +- name: Work + latitude: !secret zone_work_latitude + longitude: !secret zone_work_longitude + radius: 500 + icon: mdi:worker diff --git a/notifications/README.md b/notifications/README.md index a6479e3..90da0b2 100644 --- a/notifications/README.md +++ b/notifications/README.md @@ -2,12 +2,18 @@ Useful during development of automations, I later keep using them for simple warnings like when the dehumidifier is likely full in [`/automations/check_humidity_high.yaml`](../automations/check_humidity_high.yaml) or if a door has been left open for too long in [`/automations/check_doors.yaml`](../automations/check_doors.yaml). +## Organization -## Groups +### [`👪 ./groups.yaml`](groups.yaml) Notifications services are organized into higher-level [notification groups](https://home-assistant.io/components/notify.group/), to avoid peppering hard-coded services throughout automations. -## Pushover +### [`📢 ./lannouncer.yaml`](lannouncer.yaml) + +For audio alerts and text-to-speech messages sent to the [LANnouncer](http://www.keybounce.com/lannouncer/) Android app running on the kiosk. + + +### [`💬 ./pushover.yaml`](pushover.yaml) Notification service for cellphones and tablets. I was already using [Pushover](https://pushover.net) for other purposes, so might as well continue. diff --git a/notifications/group.yaml b/notifications/group.yaml index ffaf39c..dfe403c 100644 --- a/notifications/group.yaml +++ b/notifications/group.yaml @@ -1,12 +1,22 @@ # # Group notification # -# All notifications are sent to groups to avoid hard-coding notification +# All notifications are sent to groups to mimimize hard-coding notification # services throughout the code base. # # @link https://home-assistant.io/components/notify.group/ # - platform: group - name: group + name: Sound + services: + - service: lannouncer + +- platform: group + name: Speech + services: + - service: lannouncer + +- platform: group + name: Text services: - service: pushover diff --git a/notifications/lannouncer.yaml b/notifications/lannouncer.yaml new file mode 100644 index 0000000..5f6c38d --- /dev/null +++ b/notifications/lannouncer.yaml @@ -0,0 +1,10 @@ +# +# LANnouncer notification service for local Android devices +# +# @link http://www.keybounce.com/lannouncer/ +# @link https://home-assistant.io/components/notify.lannouncer/ +# +- platform: lannouncer + name: LANnouncer + host: !secret lannouncer_host + port: !secret lannouncer_port diff --git a/notifications/pushover.yaml b/notifications/pushover.yaml index ee5504e..c26e642 100644 --- a/notifications/pushover.yaml +++ b/notifications/pushover.yaml @@ -5,6 +5,6 @@ # @link https://home-assistant.io/components/notify.pushover/ # - platform: pushover - name: pushover + name: Pushover api_key: !secret pushover_api_key user_key: !secret pushover_user_key diff --git a/rtl4332mqtt/README.md b/rtl4332mqtt/README.md new file mode 100644 index 0000000..6fb5a50 --- /dev/null +++ b/rtl4332mqtt/README.md @@ -0,0 +1,9 @@ +# RTL433 to MQTT Bridge hass.io addon + +These are the customizable scripts for the [RTL433 to MQTT Bridge hass.io addon](https://github.com/james-fry/hassio-addons/tree/master/rtl4332mqtt). + +## Scripts + +### [`📡 ./rtl2mqtt.sh`](rtl2mqtt.sh) + +This is the main entry point for the Docker container. It is currently set to respond to only one protocol for [AcuRite's 592TXR Temp/Humidity sensor](https://www.acurite.com/indoor-temperature-sensor-and-humidity-gauge.html), therefore it would need to be modified should more than one device type need to be handled. diff --git a/rtl4332mqtt/rtl2mqtt.sh b/rtl4332mqtt/rtl2mqtt.sh index 15fe32e..d862cb5 100644 --- a/rtl4332mqtt/rtl2mqtt.sh +++ b/rtl4332mqtt/rtl2mqtt.sh @@ -152,7 +152,6 @@ PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin" CONFIG_PATH=/data/options.json MQTT_HOST="$(jq --raw-output '.mqtt_host' $CONFIG_PATH)" -#MQTT_PORT="15012" MQTT_PORT="1883" MQTT_USER="$(jq --raw-output '.mqtt_user' $CONFIG_PATH)" MQTT_PASS="$(jq --raw-output '.mqtt_password' $CONFIG_PATH)" @@ -170,9 +169,6 @@ echo "RTL_433 Protocol =" $PROTOCOL #set -x ## uncomment for MQTT logging... -/usr/bin/mosquitto_pub -h $MQTT_HOST -p $MQTT_PORT -u $MQTT_USER -P $MQTT_PASS -i RTL_433 -r -t $MQTT_TOPIC -m '{"message":"test5"}' - -#/usr/local/bin/rtl_433 -f 915000000 -F json -R $PROTOCOL | while read line /usr/local/bin/rtl_433 -f 433000000 -F json -R $PROTOCOL | while read line do # Create file with touch /tmp/rtl_433.log if logging is needed diff --git a/scenes/README.md b/scenes/README.md deleted file mode 100644 index 7100548..0000000 --- a/scenes/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Scenes - - -## LIFX cloud scenes - -See [Lights](../lights#lifx-smart-wifi-lights) section for more details. - - -## Movies scene - -Turns on some ambient lighting. - - -## Other scenes - -Need to be removed/worked on. diff --git a/scenes/movies.yaml b/scenes/movies.yaml deleted file mode 100644 index 13806da..0000000 --- a/scenes/movies.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# -# Movies scene -# -# @link /automations/media_player_start.yaml -# -- name: Movies - entities: - # Turn on the TV backlight and accent lights - light.lightpack: - state: on - switch.souvenirs_light: - state: on - switch.window_light: - state: on diff --git a/scenes/romantic.yaml b/scenes/romantic.yaml deleted file mode 100644 index b0bfacf..0000000 --- a/scenes/romantic.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# -# Romantic scene (beta) -# -# Todo: revise, replace or delete. -# -- name: Romantic - entities: - light.bedroom: - state: on - xy_color: [0.33, 0.66] - brightness: 200 - light.lounge: - state: on - xy_color: [0.33, 0.66] - brightness: 200 - light.middle: - state: on - xy_color: [0.33, 0.66] - brightness: 200 diff --git a/screenshots/device-tplink-mini.jpg b/screenshots/device-tplink-mini.jpg deleted file mode 100644 index b11bc31..0000000 Binary files a/screenshots/device-tplink-mini.jpg and /dev/null differ diff --git a/screenshots/device-tplink-mini@2x.jpg b/screenshots/device-tplink-mini@2x.jpg deleted file mode 100644 index 6b5efa2..0000000 Binary files a/screenshots/device-tplink-mini@2x.jpg and /dev/null differ diff --git a/screenshots/ui-current-conditions.png b/screenshots/ui-current-conditions.png deleted file mode 100644 index c3cc3b5..0000000 Binary files a/screenshots/ui-current-conditions.png and /dev/null differ diff --git a/screenshots/ui-current-conditions@2x.png b/screenshots/ui-current-conditions@2x.png deleted file mode 100644 index affbf28..0000000 Binary files a/screenshots/ui-current-conditions@2x.png and /dev/null differ diff --git a/screenshots/ui-horizontal-line.png b/screenshots/ui-horizontal-line.png deleted file mode 100644 index 02cf353..0000000 Binary files a/screenshots/ui-horizontal-line.png and /dev/null differ diff --git a/screenshots/ui-horizontal-line@2x.png b/screenshots/ui-horizontal-line@2x.png deleted file mode 100644 index 574e1ae..0000000 Binary files a/screenshots/ui-horizontal-line@2x.png and /dev/null differ diff --git a/screenshots/ui-weekly-forecast.png b/screenshots/ui-weekly-forecast.png deleted file mode 100644 index f743d42..0000000 Binary files a/screenshots/ui-weekly-forecast.png and /dev/null differ diff --git a/screenshots/ui-weekly-forecast@2x.png b/screenshots/ui-weekly-forecast@2x.png deleted file mode 100644 index 8b590c1..0000000 Binary files a/screenshots/ui-weekly-forecast@2x.png and /dev/null differ diff --git a/scripts/README.md b/scripts/README.md index cb15142..7fe0b63 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,7 +1,107 @@ # Scripts -Only one script remains, as all current actions and requirements are based on publish–subscribe pattern. See [`/automations`](../automations) and [`/misc/input_booleans.yaml`](../misc/input_booleans.yaml) for details. +For the most part, actions and requirements are based on publish–subscribe pattern where devices and rooms are smart-enough to respond themselves to global parameters and responsible for their own states. See [`/automations/`](../automations) and [`/misc/input_booleans.yaml`](../misc/input_booleans.yaml) for details. -## [`wakeup.yaml`](wakeup.yaml) -Quickly disables all blocking modes, therefore activating all lights. +## Smart scenes + +Smart scenes are a hybrid approach, where global parameters are used when appropriate, and some direct control is employed to achieve a specific setup. They are used both in [`/automations/`](../automations) and as a manual selector in [`/misc/input_selects.yaml`](../misc/input_selects.yaml) and [`/appdaemon/dashboards/Main.dash`](../appdaemon/dashboards/Main.dash). + + +### [`🔆 ./scene_daylight.yaml`](scene_daylight.yaml) + +Turn on all lights, and set most of the smart ones to a bright daylight white temperature. + +
+
+
+ Opening curtains +
+
+

Daylight!

+
+
+
+ +### [`🏠 ./scene_default.yaml`](scene_default.yaml) + +Used to disable scene mode and return light selectors to their default states. + + +### [`👾 ./scene_gaming.yaml`](scene_gaming.yaml) + +Set lounge smart lights to video gaming themed colours and effects, as the HTPC is used for gaming also. + +
+
+
+ Randy March playing video games +
+
+

Randy March playing video games.

+
+
+
+ +### [`📺 ./scene_movie.yaml`](scene_movie.yaml) + +Enable lounge ambiant lights and set its smart ones to television-friendly colours and effects. + +
+
+
+ Michael Jackson in Thriller +
+
+

♫♬♪ You know it's thriller, Thriller night... ♪♫♬

+
+
+
+ +### [`💏 ./scene_romantic.yaml`](scene_romantic.yaml) + +Turn on accent lights, dim some others, pick a romantic colour theme, set the mood for _looooove!_ + +
+
+
+ Quagmire's home automation +
+
+

Quagmire's Home Automation. Giggity Giggity!

+
+
+
+ +## Other scripts + +### [`👮 ./tamper_reset.yaml`](tamper_reset.yaml) + +Reset the state for tampered perimeter devices list. + +
+
+
+ Reset button +
+
+

♫♬♪ One in a Million... ♪♫♬

+
+
+
+ + +### [`☀ ./wake_up.yaml`](wake_up.yaml) + +Quickly disable all blocking modes, therefore activating all lights. + +
+
+
+ Chuck Norris doesn't turn on the light. He turns off the dark. +
+
+

Chuck Norris this.

+
+
+
diff --git a/scripts/scene_daylight.yaml b/scripts/scene_daylight.yaml new file mode 100644 index 0000000..bf6c9b9 --- /dev/null +++ b/scripts/scene_daylight.yaml @@ -0,0 +1,79 @@ +# +# Setup daylight smart scene +# +# @see /automations/scene_select.yaml +# +alias: Daylight scene +sequence: + # Enable scene mode. + - service: input_boolean.turn_on + data: + entity_id: input_boolean.scene_mode + + # Turn on all simple lights. + - service: homeassistant.turn_on + data: + entity_id: + - light.countertop + - light.island + - light.microwave + - light.sink + - switch.bedside_light + - switch.nightstand_light + - switch.souvenirs_light + - switch.window_light + + # Set smart lights to the max. + - service: light.lifx_set_state + data: + entity_id: + - group.kitchen_lights + data_template: + kelvin: 6000 + brightness_pct: 100 + + # Set LIFX lights to the max. + - service: light.lifx_set_state + data: + entity_id: + - light.shower + - light.spotlight + - light.lounge_lamp + data_template: + kelvin: 6000 + brightness_pct: 100 + transition: 2 + + # Set Aurora effect. + - service: input_select.select_option + data: + entity_id: input_select.aurora_effect + option: Daylight + + # Set bed underglow light effect. + - service: input_select.select_option + data: + entity_id: input_select.bed_effect + option: Reading + - service: homeassistant.turn_on + data: + entity_id: + - group.bed_lights + transition: 5 + + # Set ceiling wash light effect. + - service: input_select.select_option + data: + entity_id: input_select.ceiling_effect + option: Daylight + - service: homeassistant.turn_on + data: + entity_id: + - group.ceiling_lights + transition: 5 + + # Set TV backlight effect. + - service: input_select.select_option + data: + entity_id: input_select.lightpack_effect + option: Daylight diff --git a/scripts/scene_default.yaml b/scripts/scene_default.yaml new file mode 100644 index 0000000..44490b9 --- /dev/null +++ b/scripts/scene_default.yaml @@ -0,0 +1,36 @@ +# +# Setup default scene +# +# This isn't really a scene, more of a baseline state. +# +# @see /automations/scene_select.yaml +# +alias: Default scene +sequence: + # Return the Aurora effect to default. + - service: input_select.select_option + data: + entity_id: input_select.aurora_effect + option: Auto + + # Return the bed underglow light effect to default. + - service: input_select.select_option + data: + entity_id: input_select.bed_effect + option: Auto + + # Return the ceiling wash light effect to default. + - service: input_select.select_option + data: + entity_id: input_select.ceiling_effect + option: Auto + + # Return the TV backlight effect to default. + - service: input_select.select_option + data: + entity_id: input_select.lightpack_effect + option: Default + + # Remove the scene override. + - service: input_boolean.turn_off + entity_id: input_boolean.scene_mode diff --git a/scripts/scene_gaming.yaml b/scripts/scene_gaming.yaml new file mode 100644 index 0000000..de2ff27 --- /dev/null +++ b/scripts/scene_gaming.yaml @@ -0,0 +1,54 @@ +# +# Setup gaming scene +# +# @see /automations/scene_select.yaml +# +alias: Gaming scene +sequence: + # Enable scene mode. + - service: input_boolean.turn_on + data: + entity_id: input_boolean.scene_mode + + # Dim the lounge spot lights. + - service: light.lifx_set_state + data: + entity_id: + - light.spotlight + - light.lounge_lamp + data_template: + rgb_color: [80, 0, 110] + brightness_pct: 50 + transition: 5 + + # Set Aurora effect. + - service: input_select.select_option + data: + entity_id: input_select.aurora_effect + option: Synthwave + + # Turn on ceiling wash lights. + - service: homeassistant.turn_on + data: + entity_id: + - group.ceiling_lights + transition: 5 + + # Set ceiling wash light effect. + - service: input_select.select_option + data: + entity_id: input_select.ceiling_effect + option: Blissful + + # Set TV backlight effect. + - service: input_select.select_option + data: + entity_id: input_select.lightpack_effect + option: Gaming + + # Turn off some glaring kitchen lights. + - service: homeassistant.turn_off + data: + entity_id: + - light.countertop + - light.island diff --git a/scripts/scene_movie.yaml b/scripts/scene_movie.yaml new file mode 100644 index 0000000..ac06625 --- /dev/null +++ b/scripts/scene_movie.yaml @@ -0,0 +1,67 @@ +# +# Setup movie scene +# +# @see /automations/scene_select.yaml +# +alias: Movie scene +sequence: + # Enable scene mode. + - service: input_boolean.turn_on + data: + entity_id: input_boolean.scene_mode + + # Enable quiet mode. + - service: input_boolean.turn_on + data: + entity_id: input_boolean.quiet_mode + + # Turn on accent lights. + - service: homeassistant.turn_on + data: + entity_id: + - switch.souvenirs_light + - switch.window_light + + # Dim the spot lights. + # Todo: Investigate moving to https://home-assistant.io/components/light/ + - service: light.lifx_set_state + data: + entity_id: + - light.shower + - light.spotlight + - light.lounge_lamp + data_template: + kelvin: 2500 + brightness_pct: 40 + transition: 2 + + # Turn off some glaring kitchen lights. + - service: homeassistant.turn_off + data: + entity_id: + - light.countertop + - light.island + + # Set TV backlight effect. + - service: input_select.select_option + data: + entity_id: input_select.lightpack_effect + option: Movie + + # If ceiling wash lights are on, set them to their dedicated Movie scene. + - condition: state + entity_id: group.ceiling + state: 'on' + - service: input_select.select_option + data: + entity_id: input_select.ceiling_effect + option: Movie + + # If the Aurora is active, set it to its dedicated Movie scene. + - condition: state + entity_id: light.aurora + state: 'on' + - service: input_select.select_option + data: + entity_id: input_select.aurora_effect + option: Flames diff --git a/scripts/scene_romantic.yaml b/scripts/scene_romantic.yaml new file mode 100644 index 0000000..9d0be1b --- /dev/null +++ b/scripts/scene_romantic.yaml @@ -0,0 +1,75 @@ +# +# Setup romantic scene +# +# @see /automations/scene_select.yaml +# +alias: Romantic scene +sequence: + # Enable scene mode. + - service: input_boolean.turn_on + data: + entity_id: input_boolean.scene_mode + + # Enable quiet mode. + - service: input_boolean.turn_on + data: + entity_id: input_boolean.quiet_mode + + # Turn on accent lights. + - service: homeassistant.turn_on + data: + entity_id: + - switch.bedside_light + - switch.nightstand_light + - switch.souvenirs_light + - switch.window_light + + # Dim and colourize the spot lights. + - service: light.lifx_set_state + data: + entity_id: + - light.shower + - light.spotlight + - light.lounge_lamp + data_template: + color_name: magenta + brightness_pct: 50 + transition: 5 + power: True + + # Set Aurora effect. + - service: input_select.select_option + data: + entity_id: input_select.aurora_effect + option: Romantic + + # Set bed underglow light effect. + - service: input_select.select_option + data: + entity_id: input_select.bed_effect + option: Neon + - service: homeassistant.turn_on + data: + entity_id: + - group.bed_lights + transition: 5 + + # Turn off ceiling wash lights. + - service: homeassistant.turn_off + data: + entity_id: + - group.ceiling_lights + transition: 10 + + # Turn off some glaring kitchen lights. + - service: homeassistant.turn_off + data: + entity_id: + - light.countertop + - light.island + + # Set TV backlight effect. + - service: input_select.select_option + data: + entity_id: input_select.lightpack_effect + option: Romantic diff --git a/scripts/tamper_reset.yaml b/scripts/tamper_reset.yaml new file mode 100644 index 0000000..62e3dd7 --- /dev/null +++ b/scripts/tamper_reset.yaml @@ -0,0 +1,12 @@ +# +# Reset tamper variable +# +# @see /misc/variables.yaml +# +alias: Tamper location reset +sequence: + # Reset the tamper variable. + - service: variable.set_variable + data: + variable: tamper_detected + value_template: False diff --git a/scripts/wake_up.yaml b/scripts/wake_up.yaml index b9cec63..a8bf6f0 100644 --- a/scripts/wake_up.yaml +++ b/scripts/wake_up.yaml @@ -24,3 +24,9 @@ sequence: - service: input_boolean.turn_off data: entity_id: input_boolean.scene_mode + + # Reset scene. + - service: input_select.select_option + data: + entity_id: input_select.scene + option: Default diff --git a/secrets-dummy.yaml b/secrets-dummy.yaml index 2658d61..8986efa 100644 --- a/secrets-dummy.yaml +++ b/secrets-dummy.yaml @@ -1,11 +1,11 @@ -# Use this file to store secrets like usernames and passwords. -# Learn more at https://home-assistant.io/docs/configuration/secrets/ +# +# Dummy secrets file +# +# @link https://home-assistant.io/docs/configuration/secrets/ +# -aurora_host: "" +aurora_host: 127.0.0.1 aurora_api_key: "" -aurora_on: "" -aurora_off: "" -aurora_state: "" darksky_api_key: "" @@ -14,14 +14,30 @@ ebox_password: "" environment_canada_radar: "" -flic_host: "" +filesize_database: home-assistant_v2.db +filesize_log: home-assistant.log + +flic_host: 127.0.0.1 flic_port: 12345 +fully_kiosk_host: 127.0.0.1 +fully_kiosk_port: 12345 +fully_kiosk_password: "" +fully_kiosk_info: http://[host]:[port]/?cmd=deviceInfo&type=json&password=[password] + +hadashboard_dash_url: http://127.0.0.1:12345 + +homeassistant_time_zone: America/Toronto +homeassistant_whitelist_config: ./ + +lannouncer_host: 127.0.0.1 +lannouncer_port: 12345 + gtfs_data: "" -gtfs_origin_1: "" -gtfs_destination_1: "" -gtfs_origin_2: "" -gtfs_destination_2: "" +gtfs_origin_1: 0 +gtfs_destination_1: 0 +gtfs_origin_2: 0 +gtfs_destination_2: 0 gravatar_her: "" gravatar_him: "" @@ -29,9 +45,11 @@ gravatar_him: "" http_password: "" http_base_url: "" +homekit_port: 12345 + ifttt_key: "" -kodi_host: "" +kodi_host: 127.0.0.1 kodi_port: 12345 kodi_tcp_port: 12345 kodi_username: "" @@ -39,17 +57,14 @@ kodi_password: "" lifx_cloud_token: "" -limitleddled_bridge_host: "" -limitleddled_bridge_port: 12345 +limitlessled_bridge_host: 127.0.0.1 +limitlessled_bridge_port: 12345 -lightpack_host: "" +lightpack_host: 127.0.0.1 lightpack_port: 12345 lightpack_api_key: "" -lightpack_on: "" -lightpack_off: "" -lightpack_state: "" -mqtt_broker: "" +mqtt_broker: 127.0.0.1 mqtt_port: 12345 mqtt_username: "" mqtt_password: "" @@ -57,24 +72,25 @@ mqtt_password: "" nickname_her: "" nickname_him: "" -plex_host: "" +plex_host: 127.0.0.1 plex_port: 12345 plex_username: "" plex_password: "" +plex_token: "" pushover_api_key: "" pushover_user_key: "" speedtest_server_id: 12345 -tplink_bedroom_fan_host: "" -tplink_bedside_light_host: "" -tplink_dehumidifier_host: "" -tplink_nightstand_light_host: "" -tplink_souvenirs_light_host: "" -tplink_window_light_host: "" +tplink_bedroom_fan_host: 127.0.0.1 +tplink_bedside_light_host: 127.0.0.1 +tplink_dehumidifier_host: 127.0.0.1 +tplink_nightstand_light_host: 127.0.0.1 +tplink_souvenirs_light_host: 127.0.0.1 +tplink_window_light_host: 127.0.0.1 -unifi_host: "" +unifi_host: 127.0.0.1 unifi_port: 12345 unifi_username: "" unifi_password: "" @@ -82,6 +98,7 @@ unifi_password: "" waqi_token: "" waqi_location1: "" waqi_location2: "" +waqi_location3: "" zone_home_elevation: 0 zone_home_latitude: 00.00000 @@ -90,3 +107,5 @@ zone_terminal_latitude: 00.00000 zone_terminal_longitude: 00.00000 zone_work_latitude: 00.00000 zone_work_longitude: 00.00000 + +zwave_network_key: "" diff --git a/sensors/README.md b/sensors/README.md index 8688148..b4852ac 100644 --- a/sensors/README.md +++ b/sensors/README.md @@ -2,23 +2,200 @@ Each YAML file groups together all related sensors and contains details on usage. -- [`calendar.yaml`](calendar.yaml): Everything time related. -- [`climate.yaml`](climate.yaml): Indoor climate conditions. -- [`gtfs.yaml`](gtfs.yaml): [General Transit Feed Specification](http://gtfs.org), essentially bus schedules. See also [`/gtfs`](../gtfs) for performance tuning of this large dataset. -- [`health.yaml`](health.yaml): [Atmospheric pollution](https://waqi.info/), UV Index and [chances of Armageddon](https://thebulletin.org/timeline). -- [`image.yaml`](image.yaml): Data sources for some [`/cameras`](../cameras). -- [`isp.yaml`](isp.yaml): Internet service provider consumption details. -- [`light.yaml`](light.yaml): Reports on loaded effects for smart lights. -- [`misc.yaml`](misc.yaml): Everything else. -- [`network.yaml`](network.yaml): Internet connection speed and latency testing. -- [`power.yaml`](power.yaml): Battery states. -- [`system.yaml`](system.yaml): Geeky details on HASS and its hardware status. -- [`weather.yaml`](weather.yaml): Everything weather related. + +## Device sensors + +### [`😓 ./climate.yaml`](climate.yaml) + +Indoor climate conditions. + +
+
+
+ Climate Control group + Climate Control group (dark theme) +
+
+

Climate Control group.

+
+
+
+
+ Humidity group + Humidity group (dark theme) +
+
+

Humidity group.

+
+
+
+
+ Temperature group + Temperature group (dark theme) +
+
+

Temperature group.

+
+
+
+ + +### [`💡 ./light.yaml`](light.yaml) + +Reports on loaded effects for smart lights. + + +### [`🔋 ./power.yaml`](power.yaml) + +Battery levels. + +
+
+
+ Battery Levels group + Battery Levels group (dark theme) +
+
+

Battery Levels group.

+
+
+
+ + +## Data-source sensors + +### [`🌫 ./atmosphere.yaml`](atmosphere.yaml) + +[Atmospheric pollution](https://waqi.info/), UV Index and [chances of Armageddon](https://thebulletin.org/timeline). + +
+
+
+ Atmospheric Safety group + Atmospheric Safety group (dark theme) +
+
+

Atmospheric Safety group.

+
+
+
+ +### [`🚌 ./gtfs.yaml`](gtfs.yaml) + +[General Transit Feed Specification](http://gtfs.org), essentially bus schedules. See also [`/gtfs/`](../gtfs) for performance tuning of this large dataset. + +
+
+
+ Public Transit group + Public Transit group (dark theme) +
+
+

Public Transit group with schedules for the next three departures in two directions. Yellow (warning) and red (critical) highlights are using /theme/ cards defined in /customize.yaml based on how much time is left before the bus leaves. 🚌🏃

+
+
+
+ + +### [`🖼 ./image.yaml`](image.yaml) + +Data sources for some [`/cameras`](../cameras). + +
+
+
+ NOAA GeoColour satellite image + NOAA Water Vapour satellite image +
+
+

NOAA satellite images for North-America's East Coast.

+
+
+
+ + +### [`📡 ./network.yaml`](network.yaml) + +Internet connection speed and latency testing. + +
+
+
+ Network group + Network group (dark theme) +
+
+

Network group.

+
+
+
+ + +### [`🤓 ./system.yaml`](system.yaml) + +Geeky details on HASS and its hardware status. + +
+
+
+ System group + System group (dark theme) +
+
+

System group.

+
+
+
+ + +### [`🌦 ./weather.yaml`](weather.yaml) + +Everything weather related. + +
+
+
+ Today's Weather group + Today's Weather group (dark theme) +
+
+ Weekly Forecast group + Weekly Forecast group (dark theme) +
+
+

Today's weather and weekly forecast groups.

+
+
+
+ + +## Generic sensors + +### [`⏳ ./calendar.yaml`](calendar.yaml) + +Everything time related. + +
+
+
+ Calendar group + Calendar group (dark theme) +
+
+

Calendar group.

+
+
+
+ + +### [`⁉ ./misc.yaml`](misc.yaml) + +Everything else. ## Usage -Some sensors are used for information display only in [`/groups`](../groups) and [`/appdaemon/dashboards`](../appdaemon/dashboards), while others are also used for [`/automations`](../automations). +Some sensors are used for information display only in [`/groups/`](../groups) and [`/appdaemon/dashboards/`](../appdaemon/dashboards), while others are also used for [`/automations/`](../automations). ## Customization diff --git a/sensors/health.yaml b/sensors/atmosphere.yaml similarity index 60% rename from sensors/health.yaml rename to sensors/atmosphere.yaml index 68f33c6..b2e567b 100644 --- a/sensors/health.yaml +++ b/sensors/atmosphere.yaml @@ -22,6 +22,7 @@ locations: - !secret waqi_location1 - !secret waqi_location2 + - !secret waqi_location3 # @@ -33,7 +34,8 @@ round_digits: 0 entity_ids: - sensor.waqi_rivesud_de_montreal_quebec_canada - - sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada + - sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada + - sensor.waqi_drummond_montreal_canada - platform: template sensors: @@ -43,7 +45,7 @@ value_template: >- {% set index = states('sensor.aqi_exact') %} - {% if index != "unknown" %} + {% if index != 'unknown' %} {{ index | float | round }} {% else %} {{ index }} @@ -55,7 +57,7 @@ value_template: >- {% set index = states('sensor.aqi_exact') %} - {% if index != "unknown" %} + {% if index != 'unknown' %} {% set index = index | float | round %} {% if 0 <= index <= 50 %} @@ -77,23 +79,27 @@ # -# WAQI: Particulate matter 2.5μm +# WAQI: Carbon monoxide # - platform: template sensors: - aqi_particles: - friendly_name: PM2.5 - icon_template: mdi:factory + aqi_carbon_monoxide: + friendly_name: Carbon Monoxide + icon_template: mdi:fire unit_of_measurement: 'PPM' value_template: >- {% set levels = 0 %} {% set counter = 0 %} - {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != "unknown" and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.pm_2_5 is defined %} - {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.pm_2_5 %} + {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != 'unknown' and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.co is defined %} + {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.co %} + {% set counter = counter + 1 %} + {% endif %} + {% if states('sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada') != 'unknown' and states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.co is defined %} + {% set levels = levels + states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.co %} {% set counter = counter + 1 %} {% endif %} - {% if states('sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada') != "unknown" and states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.pm_2_5 is defined %} - {% set levels = levels + states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.pm_2_5 %} + {% if states('sensor.waqi_drummond_montreal_canada') != 'unknown' and states.sensor.waqi_drummond_montreal_canada.attributes.co is defined %} + {% set levels = levels + states.sensor.waqi_drummond_montreal_canada.attributes.co %} {% set counter = counter + 1 %} {% endif %} @@ -103,25 +109,25 @@ unknown {% endif %} - aqi_particles_friendly: - friendly_name: PM2.5 - icon_template: mdi:factory + aqi_carbon_monoxide_friendly: + friendly_name: Carbon Monoxide + icon_template: mdi:fire value_template: >- - {% set pm25 = states('sensor.aqi_particles') | int(-1) %} + {% set co = states('sensor.aqi_carbon_monoxide') | int(-1) %} - {% if pm25 < 0 %} + {% if co < 0 %} unknown - {% elif 0 <= pm25 <= 50 %} + {% elif 0 <= co <= 50 %} Good - {% elif 51 <= pm25 <= 100 %} + {% elif 51 <= co <= 100 %} Moderate - {% elif 101 <= pm25 <= 150 %} + {% elif 101 <= co <= 150 %} Unhealthy for Sensitive Groups - {% elif 151 <= pm25 <= 200 %} + {% elif 151 <= co <= 200 %} Unhealthy - {% elif 201 <= pm25 <= 300 %} + {% elif 201 <= co <= 300 %} Very Unhealthy - {% elif 301 <= pm25 %} + {% elif 301 <= co %} Hazardous {% else %} N/A @@ -129,23 +135,27 @@ # -# WAQI: Ozone +# WAQI: Particulate matter 2.5μm # - platform: template sensors: - aqi_ozone: - friendly_name: Ozone - icon_template: mdi:earth + aqi_particles: + friendly_name: PM2.5 + icon_template: mdi:chart-bubble unit_of_measurement: 'PPM' value_template: >- {% set levels = 0 %} {% set counter = 0 %} - {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != "unknown" and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.ozone is defined %} - {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.ozone %} + {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != 'unknown' and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.pm_2_5 is defined %} + {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.pm_2_5 %} + {% set counter = counter + 1 %} + {% endif %} + {% if states('sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada') != 'unknown' and states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.pm_2_5 is defined %} + {% set levels = levels + states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.pm_2_5 %} {% set counter = counter + 1 %} {% endif %} - {% if states('sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada') != "unknown" and states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.ozone is defined %} - {% set levels = levels + states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.ozone %} + {% if states('sensor.waqi_drummond_montreal_canada') != 'unknown' and states.sensor.waqi_drummond_montreal_canada.attributes.pm_2_5 is defined %} + {% set levels = levels + states.sensor.waqi_drummond_montreal_canada.attributes.pm_2_5 %} {% set counter = counter + 1 %} {% endif %} @@ -155,25 +165,25 @@ unknown {% endif %} - aqi_ozone_friendly: - friendly_name: Ozone - icon_template: mdi:earth + aqi_particles_friendly: + friendly_name: PM2.5 + icon_template: mdi:chart-bubble value_template: >- - {% set ozone = states('sensor.aqi_ozone') | int(-1) %} + {% set pm25 = states('sensor.aqi_particles') | int(-1) %} - {% if ozone < 0 %} + {% if pm25 < 0 %} unknown - {% elif 0 <= ozone <= 50 %} + {% elif 0 <= pm25 <= 50 %} Good - {% elif 51 <= ozone <= 100 %} + {% elif 51 <= pm25 <= 100 %} Moderate - {% elif 101 <= ozone <= 150 %} + {% elif 101 <= pm25 <= 150 %} Unhealthy for Sensitive Groups - {% elif 151 <= ozone <= 200 %} + {% elif 151 <= pm25 <= 200 %} Unhealthy - {% elif 201 <= ozone <= 300 %} + {% elif 201 <= pm25 <= 300 %} Very Unhealthy - {% elif 301 <= ozone %} + {% elif 301 <= pm25 %} Hazardous {% else %} N/A @@ -192,12 +202,16 @@ value_template: >- {% set levels = 0 %} {% set counter = 0 %} - {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != "unknown" and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.nitrogen_dioxide is defined %} + {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != 'unknown' and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.nitrogen_dioxide is defined %} {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.nitrogen_dioxide %} {% set counter = counter + 1 %} {% endif %} - {% if states('sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada') != "unknown" and states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.nitrogen_dioxide is defined %} - {% set levels = levels + states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.nitrogen_dioxide %} + {% if states('sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada') != 'unknown' and states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.nitrogen_dioxide is defined %} + {% set levels = levels + states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.nitrogen_dioxide %} + {% set counter = counter + 1 %} + {% endif %} + {% if states('sensor.waqi_drummond_montreal_canada') != 'unknown' and states.sensor.waqi_drummond_montreal_canada.attributes.nitrogen_dioxide is defined %} + {% set levels = levels + states.sensor.waqi_drummond_montreal_canada.attributes.nitrogen_dioxide %} {% set counter = counter + 1 %} {% endif %} @@ -233,23 +247,27 @@ # -# WAQI: Carbon monoxide +# WAQI: Ozone # - platform: template sensors: - aqi_carbon_monoxide: - friendly_name: Carbon Monoxide - icon_template: mdi:fire + aqi_ozone: + friendly_name: Ozone + icon_template: mdi:earth unit_of_measurement: 'PPM' value_template: >- {% set levels = 0 %} {% set counter = 0 %} - {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != "unknown" and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.co is defined %} - {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.co %} + {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != 'unknown' and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.ozone is defined %} + {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.ozone %} + {% set counter = counter + 1 %} + {% endif %} + {% if states('sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada') != 'unknown' and states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.ozone is defined %} + {% set levels = levels + states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.ozone %} {% set counter = counter + 1 %} {% endif %} - {% if states('sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada') != "unknown" and states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.co is defined %} - {% set levels = levels + states.sensor.waqi_longueuil__secteur_du_parc_oceanie_brossard_quebec_canada.attributes.co %} + {% if states('sensor.waqi_drummond_montreal_canada') != 'unknown' and states.sensor.waqi_drummond_montreal_canada.attributes.ozone is defined %} + {% set levels = levels + states.sensor.waqi_drummond_montreal_canada.attributes.ozone %} {% set counter = counter + 1 %} {% endif %} @@ -259,31 +277,87 @@ unknown {% endif %} - aqi_carbon_monoxide_friendly: - friendly_name: Carbon Monoxide - icon_template: mdi:fire + aqi_ozone_friendly: + friendly_name: Ozone + icon_template: mdi:earth value_template: >- - {% set co = states('sensor.aqi_carbon_monoxide') | int(-1) %} + {% set ozone = states('sensor.aqi_ozone') | int(-1) %} - {% if co < 0 %} + {% if ozone < 0 %} unknown - {% elif 0 <= co <= 50 %} + {% elif 0 <= ozone <= 50 %} Good - {% elif 51 <= co <= 100 %} + {% elif 51 <= ozone <= 100 %} Moderate - {% elif 101 <= co <= 150 %} + {% elif 101 <= ozone <= 150 %} Unhealthy for Sensitive Groups - {% elif 151 <= co <= 200 %} + {% elif 151 <= ozone <= 200 %} Unhealthy - {% elif 201 <= co <= 300 %} + {% elif 201 <= ozone <= 300 %} Very Unhealthy - {% elif 301 <= co %} + {% elif 301 <= ozone %} Hazardous {% else %} N/A {% endif %} +# +# WAQI: Sulphur dioxide +# +- platform: template + sensors: + aqi_sulphur_dioxide: + friendly_name: Sulphur Dioxide + icon_template: mdi:factory + unit_of_measurement: 'PPM' + value_template: >- + {% set levels = 0 %} + {% set counter = 0 %} + {% if states('sensor.waqi_rivesud_de_montreal_quebec_canada') != 'unknown' and states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.sulfur_dioxide is defined %} + {% set levels = levels + states.sensor.waqi_rivesud_de_montreal_quebec_canada.attributes.sulfur_dioxide %} + {% set counter = counter + 1 %} + {% endif %} + {% if states('sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada') != 'unknown' and states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.sulfur_dioxide is defined %} + {% set levels = levels + states.sensor.waqi_brossard__secteur_du_parc_sorbonne_quebec_canada.attributes.sulfur_dioxide %} + {% set counter = counter + 1 %} + {% endif %} + {% if states('sensor.waqi_drummond_montreal_canada') != 'unknown' and states.sensor.waqi_drummond_montreal_canada.attributes.sulfur_dioxide is defined %} + {% set levels = levels + states.sensor.waqi_drummond_montreal_canada.attributes.sulfur_dioxide %} + {% set counter = counter + 1 %} + {% endif %} + + {% if counter > 0 %} + {{ (levels / counter) | round }} + {% else %} + unknown + {% endif %} + + aqi_sulphur_dioxide_friendly: + friendly_name: Sulphur Dioxide + icon_template: mdi:factory + value_template: >- + {% set so2 = states('sensor.aqi_sulphur_dioxide') | int(-1) %} + + {% if so2 < 0 %} + unknown + {% elif 0 <= so2 <= 50 %} + Good + {% elif 51 <= so2 <= 100 %} + Moderate + {% elif 101 <= so2 <= 150 %} + Unhealthy for Sensitive Groups + {% elif 151 <= so2 <= 200 %} + Unhealthy + {% elif 201 <= so2 <= 300 %} + Very Unhealthy + {% elif 301 <= so2 %} + Off the Scale + {% else %} + N/A + {% endif %} + + # # Ultraviolet rays # diff --git a/sensors/calendar.yaml b/sensors/calendar.yaml index e2bba3d..8d53ba7 100644 --- a/sensors/calendar.yaml +++ b/sensors/calendar.yaml @@ -1,13 +1,3 @@ -# -# Moon phases -# -# Todo: verify the need for dis disabled snesor. -# -# @link https://home-assistant.io/components/sensor.moon/ -# -# - platform: moon - - # # Time & Date # @@ -24,34 +14,40 @@ - platform: template sensors: - day: - friendly_name: Day + date_friendly: + friendly_name: Date icon_template: mdi:calendar-today + friendly_name_template: >- + {% set date = states('sensor.date') %} + {% set datetime = strptime(date, '%Y-%m-%d') %} + {{ datetime.strftime('%A') }} value_template: >- {# Using a sensor instead of now() to avoid constant updating. #} {% set date = states('sensor.date') %} {% set datetime = strptime(date, '%Y-%m-%d') %} + {% set month = datetime.strftime('%B') %} + {% set day = datetime.strftime('%d') | int %} - {{ datetime.strftime('%A') }} + {{ month }} {{ day }} - date_friendly: + date_long: friendly_name: Date icon_template: mdi:calendar-today value_template: >- {# Using a sensor instead of now() to avoid constant updating. #} {% set date = states('sensor.date') %} {% set datetime = strptime(date, '%Y-%m-%d') %} - + {% set weekday = datetime.strftime('%A') %} {% set month = datetime.strftime('%B') %} {% set day = datetime.strftime('%d') | int %} {% - set suffix = "st" if (day % 10 == 1 and day != 11) - else "nd" if (day % 10 == 2 and day != 12) - else "rd" if (day % 10 == 3 and day != 13) - else "th" + set suffix = 'st' if (day % 10 == 1 and day != 11) + else 'nd' if (day % 10 == 2 and day != 12) + else 'rd' if (day % 10 == 3 and day != 13) + else 'th' %} - {{ month }} {{ day }} + {{ weekday }} {{ month }} {{ day }}{{ suffix }} time_friendly: friendly_name: Time @@ -62,6 +58,62 @@ {{ hour }}:{{ minutes }} + time_long: + friendly_name: Time + icon_template: mdi:clock + value_template: >- + {% set hour = states('sensor.time').split(':')[0] | int %} + {% set minute = states('sensor.time').split(':')[1] | int %} + + {% set minute_str = '' %} + {% if minute == 15 or minute == 45 %} + {% set minute_str = 'a quarter' %} + {% elif minute == 30 %} + {% set minute_str = 'half' %} + {% else %} + {% if minute > 30 %} + {% set minute_str = (60 - minute) | string %} + {% elif minute != 0 %} + {% set minute_str = minute | string %} + {% endif %} + + {% if minute_str %} + {% if minute > 1 %} + {% set minute_str = minute_str + ' minutes' %} + {% else %} + {% set minute_str = minute_str + ' minute' %} + {% endif %} + {% endif %} + {% endif %} + + {% if minute > 30 %} + {% set minute_str = minute_str + ' to' %} + {% set hour = hour + 1 %} + {% if hour >= 24 %} + {% set hour = hour - 24 %} + {% endif %} + {% elif minute > 0 %} + {% set minute_str = minute_str + ' past' %} + {% endif %} + + {% if hour == 0 %} + {% set hour_str = 'midnight' %} + {% elif hour == 12 %} + {% set hour_str = 'noon' %} + {% elif hour > 12 %} + {% set hour_str = hour - 12 %} + {% else %} + {% set hour_str = hour %} + {% endif %} + + {% if minute_str %} + {{ minute_str }} {{ hour_str }} + {% elif hour != 0 and hour != 12 %} + {{ hour_str }} O'Clock + {% else %} + {{ hour_str }} + {% endif %} + after_tomorrow: friendly_name: After Tomorrow value_template: >- @@ -93,7 +145,7 @@ {% set year = datetime.year %} {% set days = 31 if month in [1,3,5,7,8,10,12] else 30 if month in [4,6,9,11] - else 29 if as_timestamp(strptime(year|string + '-02-29', "%Y-%m-%d")) + else 29 if as_timestamp(strptime(year|string + '-02-29', '%Y-%m-%d')) else 28 %} @@ -123,7 +175,100 @@ {% endif %} value_template: >- {% if is_state('sun.sun', 'above_horizon') %} - sets at {% set timestamp = as_timestamp(states.sun.sun.attributes.next_setting) | timestamp_custom("%H:%M") %} {{ timestamp.lstrip("0") }} + sets at {% set timestamp = as_timestamp(states.sun.sun.attributes.next_setting) | timestamp_custom('%H:%M') %} {{ timestamp.lstrip('0') }} {% else %} - rises at {% set timestamp = as_timestamp(states.sun.sun.attributes.next_rising) | timestamp_custom("%H:%M") %} {{ timestamp.lstrip("0") }} + rises at {% set timestamp = as_timestamp(states.sun.sun.attributes.next_rising) | timestamp_custom('%H:%M') %} {{ timestamp.lstrip('0') }} + {% endif %} + + sun_state_friendly: + friendly_name: Sun + icon_template: >- + {% if is_state('sun.sun', 'above_horizon') %} + mdi:weather-sunny + {% else %} + mdi:weather-night + {% endif %} + value_template: >- + {% set current = as_timestamp(strptime(states('sensor.time__date'), '%H:%M, %Y-%m-%d')) %} + {% set dusk = as_timestamp(states.sun.sun.attributes.next_dusk) %} + + {% if current <= dusk %} + {# output example "will set at around 8." #} + {# output example "will set at around a quarter past 8." #} + {# output example "will set at around 8 and a half." #} + {# output example "will set at around a quarter to 9." #} + {# output example "will set in a few minutes." #} + {# output example "is setting." #} + + {% set setting = as_timestamp(states.sun.sun.attributes.next_setting) %} + + {% if current >= setting %} + is setting + {% elif (setting - current) <= 60*30 %} + will set in a few minutes + {% else %} + {% set hour = setting|timestamp_custom('%H') | int %} + {% set minute = setting|timestamp_custom('%M') | int %} + + {% set minute_friendly = '' %} + {% set half = false %} + + {% if minute >= 10 and minute <= 20 %} + {% set minute_friendly = 'a quarter past ' %} + {% elif minute > 20 and minute < 40 %} + {% set half = true %} + {% elif minute >= 40 and minute <= 50 %} + {% set minute_friendly = 'a quarter to ' %} + {% set hour = hour + 1 %} + {% elif minute > 50 %} + {% set hour = hour + 1 %} + {% endif %} + + {% if hour >= 24 %} + {% set hour = hour - 24 %} + {% endif %} + {% if hour == 0 %} + {% set hour_friendly = 'midnight' %} + {% elif hour == 12 %} + {% set hour_friendly = 'noon' %} + {% elif hour > 12 %} + {% set hour_friendly = hour - 12 %} + {% else %} + {% set hour_friendly = hour %} + {% endif %} + + {% if half %} + will set at around {{ hour_friendly }} and a half + {% else %} + will set at around {{ minute_friendly }}{{ hour_friendly }} + {% endif %} + + {% endif %} + {% else %} + {# output example "will rise in about 7 hours." #} + {# output example "will rise in about 7 and a half hours." #} + {# output example "will rise in a few minutes." #} + {# output example "is rising." #} + + {% set dawn = as_timestamp(states.sun.sun.attributes.next_dawn) %} + {% set rising = as_timestamp(states.sun.sun.attributes.next_rising) %} + + {% set diff = ((rising - current) / 60 / 60) %} + {% set hour = diff | int %} + {% set minute = (diff - hour) | round(2) %} + + {% if hour %} + {% if minute > 0.66 %} + {% set hour = hour + 1 %} + {% elif minute > 0.33 %} + {% set minute_friendly = ' and a half' %} + {% endif %} + + will rise in about {{hour}}{{ minute_friendly }} hour{% if hour > 0 %}s{% endif %} + {% elif (rising - dawn) < 0%} + is rising + {% else %} + will rise in a few minutes + {% endif %} + {% endif %} diff --git a/sensors/climate.yaml b/sensors/climate.yaml index 2a81efb..4738cbc 100644 --- a/sensors/climate.yaml +++ b/sensors/climate.yaml @@ -17,6 +17,23 @@ unit_of_measurement: '°C' value_template: '{{ value_json.temperature_C | round }}' +- platform: filter + name: Bedroom Humidity Filtered + entity_id: sensor.bedroom_humidity + filters: + - filter: lowpass + time_constant: 10 + precision: 1 + +- platform: filter + name: Bedroom Temperature Filtered + entity_id: sensor.bedroom_temperature + filters: + - filter: lowpass + time_constant: 10 + precision: 1 + + # # Lounge climate # @@ -26,19 +43,35 @@ friendly_name: Lounge Humidity unit_of_measurement: '%' icon_template: mdi:water-percent - value_template: "{{ states('sensor.aeotec_zw100_multisensor_6_relative_humidity') | round }}" + value_template: "{{ states('sensor.lounge_multisensor_relative_humidity') | round }}" lounge_temperature: friendly_name: Lounge Temperature unit_of_measurement: '°C' icon_template: mdi:thermometer - value_template: "{{ states('sensor.aeotec_zw100_multisensor_6_temperature') | round }}" + value_template: "{{ states('sensor.lounge_multisensor_temperature') | round }}" lounge_luminance: friendly_name: Lounge Luminance unit_of_measurement: 'lux' icon_template: mdi:blur - value_template: "{{ states('sensor.aeotec_zw100_multisensor_6_luminance') | round }}" + value_template: "{{ states('sensor.lounge_multisensor_luminance') | round }}" + +- platform: filter + name: Lounge Humidity Filtered + entity_id: sensor.lounge_humidity + filters: + - filter: lowpass + time_constant: 10 + precision: 1 + +- platform: filter + name: Lounge Temperature Filtered + entity_id: sensor.lounge_temperature + filters: + - filter: lowpass + time_constant: 10 + precision: 1 # @@ -52,8 +85,8 @@ type: mean round_digits: 0 entity_ids: - - sensor.lounge_temperature - - sensor.bedroom_temperature + - sensor.bedroom_temperature_filtered + - sensor.lounge_temperature_filtered - platform: template sensors: @@ -68,15 +101,18 @@ # Average humidity # # Helps compensate for lack of accuracy of each active sensor. -# They all claim to be precise, but precision doesn't mean accuracy! +# They all claim to be precise, but precision doesn't mean accuracy nor +# calibration! +# +# @todo calibrate all sensors. # - platform: min_max name: Average Humidity Exact type: mean round_digits: 1 entity_ids: - - sensor.lounge_humidity - - sensor.bedroom_humidity + - sensor.bedroom_humidity_filtered + - sensor.lounge_humidity_filtered - platform: template sensors: diff --git a/sensors/gtfs.yaml b/sensors/gtfs.yaml index 1970ba1..6eafcf8 100644 --- a/sensors/gtfs.yaml +++ b/sensors/gtfs.yaml @@ -21,7 +21,7 @@ origin: !secret gtfs_origin_1 destination: !secret gtfs_destination_1 data: !secret gtfs_data - scan_interval: 65 + scan_interval: 60 position: 2 - platform: gtfs @@ -29,7 +29,7 @@ origin: !secret gtfs_origin_1 destination: !secret gtfs_destination_1 data: !secret gtfs_data - scan_interval: 70 + scan_interval: 60 position: 3 - platform: gtfs @@ -44,7 +44,7 @@ origin: !secret gtfs_origin_2 destination: !secret gtfs_destination_2 data: !secret gtfs_data - scan_interval: 65 + scan_interval: 60 position: 2 - platform: gtfs @@ -52,7 +52,7 @@ origin: !secret gtfs_origin_2 destination: !secret gtfs_destination_2 data: !secret gtfs_data - scan_interval: 70 + scan_interval: 60 position: 3 - platform: template diff --git a/sensors/image.yaml b/sensors/image.yaml index 81a3bbc..a734cf7 100644 --- a/sensors/image.yaml +++ b/sensors/image.yaml @@ -12,7 +12,10 @@ resource: http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US icon_template: mdi:link-variant scan_interval: 3600 - value_template: "{{ value_json.images[0].urlbase }}" + value_template: >- + {% if value_json and value_json.images[0] and value_json.images[0].urlbase %} + {{ value_json.images[0].urlbase }} + {% endif %} - platform: rest name: Bing Wallpaper Info @@ -20,7 +23,11 @@ icon_template: mdi:information-outline entity_id: - sensor.bing_wallpaper - value_template: "{{ value_json.images[0].copyright.split(' (')[0] }}" + value_template: >- + {% if value_json and value_json.images[0] and value_json.images[0].copyright %} + {{ value_json.images[0].copyright.split(' (')[0] }} + {% endif %} + # # NASA's Astronomy Picture of the Day @@ -39,7 +46,7 @@ attribute: "src" - platform: scrape - name: APOD Title + name: APOD Info resource: https://apod.nasa.gov/apod/astropix.html scan_interval: 3600 select: "center > b" diff --git a/sensors/isp.yaml b/sensors/isp.yaml deleted file mode 100644 index 8b43d3f..0000000 --- a/sensors/isp.yaml +++ /dev/null @@ -1,63 +0,0 @@ -# -# EBOX.ca ISP bandwidth usage -# -# @see /custom_components/sensor/ebox.py -# -# @link https://client.ebox.ca/ -# @link https://home-assistant.io/components/sensor.ebox/ -# -- platform: ebox - username: !secret ebox_username - password: !secret ebox_password - scan_interval: 900 - monitored_variables: - - before_offpeak_download - - before_offpeak_upload - - download - - limit - - usage - -- platform: template - sensors: - ebox_usage_friendly: - friendly_name: Monthly Usage - icon_template: mdi:percent - unit_of_measurement: '%' - value_template: >- - {% set usage = states('sensor.ebox_usage') %} - - {% if usage != "unknown" %} - {{ usage|round(0) }} - {% else %} - unknown - {% endif %} - - ebox_download_remaining: - friendly_name: Remaining Downloads - icon_template: mdi:briefcase-download - unit_of_measurement: 'Gb' - value_template: >- - {% set limit = states('sensor.ebox_data_limit') %} - {% set download = states('sensor.ebox_download') %} - - {% if limit != "unknown" and download != "unknown" %} - {{ (limit|float - download|float) | int }} - {% else %} - unknown - {% endif %} - - ebox_download_daily_capacity: - friendly_name: Daily Capacity - icon_template: mdi:speedometer - unit_of_measurement: 'Gb' - value_template: >- - {% set download = states('sensor.ebox_download_remaining') %} - {% set days = states('sensor.days_remaining_in_month') %} - - {% if download == "unknown" or days == "unknown" %} - unknown - {% elif download|float > 0 and days|int > 0 %} - {{ (download|float / days|int) | int }} - {% else %} - 0 - {% endif %} diff --git a/sensors/light.yaml b/sensors/light.yaml index 037242c..6937b52 100644 --- a/sensors/light.yaml +++ b/sensors/light.yaml @@ -1,3 +1,36 @@ +# +# Fully Kiosk Browser screen brightness +# +# Disabled until deemed useful or not. +# +# Ressource URL: +# http://[host]:[port]/?cmd=deviceInfo&type=json&password=[password] +# +# @link https://community.home-assistant.io/t/fully-kiosk-browser/41675 +# @link https://www.ozerov.de/fully-kiosk-browser/#rest +# +# - platform: rest +# name: Kiosk Brightness +# resource: !secret fully_kiosk_info +# json_attributes: +# - screenBrightness +# value_template: >- +# {{ value_json.screenBrightness }} + + +# +# Nanoleaf Aurora loaded effect +# +# @see /appdaemon/dashboards/Switchboard.dash +# @see /customize.yaml +# +- platform: template + sensors: + aurora_effect_loaded: + friendly_name: Aurora Effect Loaded + value_template: '{{ states.light.aurora.attributes.effect }}' + + # # Bed glow lights loaded effect # @@ -9,7 +42,7 @@ bed_effect_loaded: friendly_name: Bed Effect Loaded value_template: >- - {% if is_state('group.bed', 'on') %} + {% if is_state('group.bed_lights', 'on') %} {{ states('variable.bed_effect') }} {% endif %} @@ -25,19 +58,22 @@ ceiling_effect_loaded: friendly_name: Ceiling Effect Loaded value_template: >- - {% if is_state('group.ceiling', 'on') %} + {% if is_state('group.ceiling_lights', 'on') %} {{ states('variable.ceiling_effect') }} {% endif %} # -# Nanoleaf Aurora loaded effect +# Lightpack TV backlight loaded effect # # @see /appdaemon/dashboards/Switchboard.dash # @see /customize.yaml # - platform: template sensors: - aurora_effect_loaded: - friendly_name: Aurora Effect Loaded - value_template: '{{ states.light.aurora.attributes.effect }}' + lightpack_effect_loaded: + friendly_name: Lightpack Effect Loaded + value_template: >- + {% if is_state('light.lightpack', 'on') %} + {{ states('variable.lightpack_effect') }} + {% endif %} diff --git a/sensors/misc.yaml b/sensors/misc.yaml index 400a9c0..2868a2b 100644 --- a/sensors/misc.yaml +++ b/sensors/misc.yaml @@ -1,7 +1,12 @@ # # Horizontal lines, for cosmetic separation of sensors in the UI. # -# Actual styling is done in `customize.yaml` and `customize_glob.yaml`. +# Actual styling is done in "customize" files. +# +# @see /customize.yaml +# @see /customize_glob.yaml +# @see /www/custom_ui/state-card-hline.html +# @see /www/custom_ui/state-card-hline_es5.html # # @link https://github.com/covrig/homeassistant-hline # @@ -10,6 +15,9 @@ hline_dashed: value_template: hline + hline_dashed_2: + value_template: hline + # # Current modes @@ -23,7 +31,7 @@ icon_template: mdi:emoticon-happy value_template: >- {% set counter = 0 %} - {% set modes = "" %} + {% set modes = '' %} {% if is_state('input_boolean.nap_mode', 'on') %} {% set modes = modes + '+ Nap ' %} {% set counter = counter + 1 %} @@ -40,12 +48,12 @@ {% set modes = modes + '+ Scene ' %} {% set counter = counter + 1 %} {% endif %} - {% if modes == "" %} + {% if modes == '' %} {% set modes = 'Regular ' %} {% set counter = counter + 1 %} {% endif %} - {{modes.lstrip("+")}}mode + {{ modes.lstrip('+') }}mode {%- if counter > 1 -%} s {% endif %} @@ -56,14 +64,18 @@ # # @link http://www.lifestalker.com/2017/04/four-word-quotes.html # +- platform: random + name: Good Vibes index + scan_interval: 60 + maximum: 42 + - platform: template sensors: good_vibes: friendly_name: Good Vibes icon_template: mdi:emoticon-happy value_template: >- - {# Fetch a scheduled sensor to avoid updating this template non-stop. #} - {% set time = states('sensor.time') %} + {% set index = states('sensor.good_vibes_index') | int %} {% set vibes = [ "Be great.", "Be happy!", @@ -110,4 +122,4 @@ "Your time is now.", ] %} - {{ vibes|random }} + {{ vibes[index] }} diff --git a/sensors/network.yaml b/sensors/network.yaml index cfba26b..fb33a40 100644 --- a/sensors/network.yaml +++ b/sensors/network.yaml @@ -1,20 +1,71 @@ # -# Fast.com network speed testing +# EBOX.ca ISP bandwidth usage # -# Actual performance is limited by the hosts NIC throughout. -# -# Todo: Check if this disabled sensor is superfluous. +# @see /custom_components/sensor/ebox.py # -# @link https://home-assistant.io/components/sensor.fastdotcom/ +# @link https://client.ebox.ca/ +# @link https://home-assistant.io/components/sensor.ebox/ # -# - platform: fastdotcom -# hour: -# - 3 -# - 9 -# - 15 -# - 21 -# minute: -# - 15 +- platform: ebox + username: !secret ebox_username + password: !secret ebox_password + scan_interval: 900 + monitored_variables: + - before_offpeak_download + - before_offpeak_upload + - download + - limit + - usage + +- platform: template + sensors: + ebox_usage_friendly: + friendly_name: Monthly Usage + icon_template: mdi:percent + unit_of_measurement: '%' + value_template: >- + {% set usage = states('sensor.ebox_usage') %} + + {% if usage != 'unknown' %} + {{ usage | round }} + {% else %} + unknown + {% endif %} + + ebox_download_remaining: + friendly_name: Remaining Downloads + icon_template: mdi:briefcase-download + unit_of_measurement: 'Gb' + value_template: >- + {% set limit = states('sensor.ebox_data_limit') %} + {% set download = states('sensor.ebox_download') %} + + {% if limit != 'unknown' and limit|int == 0 %} + ∞ + {% elif limit != 'unknown' and download != 'unknown' %} + {{ (limit|float - download|float) | int }} + {% else %} + unknown + {% endif %} + + ebox_download_daily_capacity: + friendly_name: Daily Capacity + icon_template: mdi:speedometer + unit_of_measurement: 'Gb' + value_template: >- + {% set limit = states('sensor.ebox_data_limit') %} + {% set download = states('sensor.ebox_download_remaining') %} + {% set days = states('sensor.days_remaining_in_month') %} + + {% if limit != 'unknown' and limit|int == 0 %} + ∞ + {% elif download == 'unknown' or days == 'unknown' %} + unknown + {% elif download|float > 0 and days|int > 0 %} + {{ (download|float / days|int) | int }} + {% else %} + 0 + {% endif %} # diff --git a/sensors/power.yaml b/sensors/power.yaml index 1599f3b..8542746 100644 --- a/sensors/power.yaml +++ b/sensors/power.yaml @@ -1,3 +1,29 @@ +# +# Fully Browser kiosk battery monitoring +# +# Licensed application running in kiosk mode on an Acer B3-A40 Android tablet. +# +# @link https://github.com/daemondazz/homeassistant-displays +- platform: template + sensors: + kiosk_battery: + friendly_name: Kiosk battery + unit_of_measurement: '%' + value_template: >- + {{ states.display.kiosk.attributes.battery_level }} + icon_template: >- + {% set battery_level = states.display.kiosk.attributes.battery_level | default(0) | int %} + {% set battery_round = (battery_level / 10) | int * 10 %} + + {% if battery_round >= 100 %} + mdi:battery + {% elif battery_round > 0 %} + mdi:battery-{{ battery_round }} + {% else %} + mdi:battery-outline + {% endif %} + + # # AcuRite battery monitoring # @@ -44,7 +70,7 @@ # -# Aeotec battery monitoring +# ZWave battery monitoring # # @link https://aeotec.com/z-wave-door-window-sensor # @link https://aeotec.com/z-wave-sensor @@ -55,15 +81,15 @@ friendly_name: Front Door Sensor Battery unit_of_measurement: '%' value_template: >- - {% set battery_level = states.zwave.aeotec_zw120_door_window_sensor_gen5.attributes.battery_level | default(0) | int %} + {% set battery_level = states.zwave.front_door.attributes.battery_level | default(0) | int %} {% if battery_level %} {{ battery_level | round }} {% else %} - {{ states('zwave.aeotec_zw120_door_window_sensor_gen5') }} + {{ states('zwave.front_door') }} {%- endif %} icon_template: >- - {% set battery_level = states.zwave.aeotec_zw120_door_window_sensor_gen5.attributes.battery_level | default(0) | int %} + {% set battery_level = states.zwave.front_door.attributes.battery_level | default(0) | int %} {% set battery_round = (battery_level / 10) | int * 10 %} {% if battery_round >= 100 %} @@ -78,15 +104,15 @@ friendly_name: Lounge Multisensor Battery unit_of_measurement: '%' value_template: >- - {% set battery_level = states.zwave.aeotec_zw100_multisensor_6.attributes.battery_level | default(0) %} + {% set battery_level = states.zwave.lounge_multisensor.attributes.battery_level | default(0) %} {% if battery_level %} {{ battery_level | round }} {% else %} - {{ states('zwave.aeotec_zw100_multisensor_6') }} + {{ states('zwave.lounge_multisensor') }} {%- endif %} icon_template: >- - {% set battery_level = states.zwave.aeotec_zw100_multisensor_6.attributes.battery_level | default(0) | int %} + {% set battery_level = states.zwave.lounge_multisensor.attributes.battery_level | default(0) | int %} {% set battery_round = (battery_level / 10) | int * 10 %} {% if battery_round >= 100 %} diff --git a/sensors/security.yaml b/sensors/security.yaml new file mode 100644 index 0000000..d97622c --- /dev/null +++ b/sensors/security.yaml @@ -0,0 +1,107 @@ +# +# Door status +# +# Returns a comma-separated list of doors currently open. +# +# @see /automations/doors_verify.yaml +# +- platform: template + sensors: + doors_status: + friendly_name_template: >- + {% if is_state('input_boolean.doors_open', 'on') %} + Doors open + {% else %} + External doors + {% endif %} + icon_template: >- + {% if is_state('input_boolean.doors_open', 'on') %} + mdi:door-open + {% else %} + mdi:door-closed + {% endif %} + value_template: >- + {% set dummy = is_state('input_boolean.doors_open', 'on') %} + {% set value = '' %} + {% if is_state('binary_sensor.front_door_sensor', 'on') %} + {% set value = value + 'Front Door,' %} + {% endif %} + {% set value = value[:-1] %} + + {% if value != '' %} + {{ value }} + {% else %} + Closed + {% endif %} + + +# +# Motion detection status +# +# Returns a comma-separated list of locations where motion is detected. +# +# @see /automations/motion_start.yaml +# +- platform: template + sensors: + motion_status: + friendly_name_template: >- + {% if is_state('input_boolean.motion_detected', 'on') %} + Motion detected + {% else %} + Motion monitoring + {% endif %} + icon_template: >- + {% if is_state('input_boolean.motion_detected', 'on') %} + mdi:walk + {% else %} + mdi:radar + {% endif %} + value_template: >- + {% set dummy = is_state('input_boolean.motion_detected', 'on') %} + {% set value = '' %} + {% if is_state('binary_sensor.kiosk_motion_auto', 'on') %} + {% set value = value + ' Kiosk,' %} + {% endif %} + {% if is_state('binary_sensor.lounge_multisensor_sensor', 'on') %} + {% set value = value + ' Lounge,' %} + {% endif %} + {% set value = value[:-1] %} + + {% if value != '' %} + {{ value }} + {% else %} + OK + {% endif %} + + +# +# Tampering status +# +# Returns a comma-separated list of perimeter devices being tampered with. +# +# @see /automations/tamper_start.yaml +# @see /misc/variables.yaml +# +- platform: template + sensors: + tamper_status: + friendly_name_template: >- + {% if is_state('input_boolean.tamper_detected', 'on') %} + Tampering detected + {% else %} + Tamper monitoring + {% endif %} + icon_template: >- + {% if is_state('input_boolean.tamper_detected', 'on') %} + mdi:home-alert + {% else %} + mdi:security-home + {% endif %} + value_template: >- + {% set dummy = is_state('input_boolean.tamper_detected', 'on') %} + {% if not is_state('variable.tamper_detected', 'False') %} + {{ states('variable.tamper_detected') }} + {% else %} + OK + {% endif %} diff --git a/sensors/system.yaml b/sensors/system.yaml index f4b703c..3938d13 100644 --- a/sensors/system.yaml +++ b/sensors/system.yaml @@ -44,7 +44,7 @@ friendly_name: Home Assistant Version icon_template: mdi:update value_template: >- - {% if states('sensor.current_version') != "unknown" %} + {% if states('sensor.current_version') != 'unknown' %} Home Assistant {{ states('sensor.current_version') }} {% else %} Home Assistant @@ -54,7 +54,7 @@ friendly_name: Update Available icon_template: mdi:update value_template: >- - {% if states('updater.updater') != "unknown" %} + {% if states('updater.updater') != 'unknown' %} Update available: {{ states('updater.updater') }} {% endif %} @@ -67,22 +67,22 @@ # - platform: template sensors: - disk_used_percent: - friendly_name: Disk Used /home + disk_use_percent: + friendly_name: Disk Use /home icon_template: mdi:harddisk unit_of_measurement: '%' value_template: >- - {% set disk_used = states('sensor.disk_used_home') | float %} + {% set disk_use = states('sensor.disk_use_home') | float %} {% set disk_free = states('sensor.disk_free_home') | float %} - {{ (100 * disk_used / (disk_used + disk_free)) | round }} + {{ (100 * disk_use / (disk_use + disk_free)) | round }} disk_free_percent: friendly_name: Disk Free /home icon_template: mdi:harddisk unit_of_measurement: '%' value_template: >- - {{ 100 - states('sensor.disk_used_percent') | float | round }} + {{ 100 - states('sensor.disk_use_percent') | float | round }} # @@ -93,22 +93,22 @@ # - platform: template sensors: - ram_used_percent: - friendly_name: RAM Used + memory_use_percent: + friendly_name: Memory Use icon_template: mdi:memory unit_of_measurement: '%' value_template: >- - {% set ram_used = states('sensor.ram_used') | float %} - {% set ram_free = states('sensor.ram_available') | float %} + {% set memory_use = states('sensor.memory_use') | float %} + {% set memory_free = states('sensor.memory_free') | float %} - {{ (100 * ram_used / (ram_used + ram_free)) | round }} + {{ (100 * memory_use / (memory_use + memory_free)) | round }} - ram_free_percent: - friendly_name: RAM Free + memory_free_percent: + friendly_name: Memory Free icon_template: mdi:memory unit_of_measurement: '%' value_template: >- - {{ 100 - states('sensor.ram_used_percent') | float | round }} + {{ 100 - states('sensor.memory_use_percent') | float | round }} # @@ -241,9 +241,9 @@ icon_template: mdi:chip unit_of_measurement: '%' value_template: >- - {% set load1 = '{0:0.2f}'.format(states('sensor.average_load_1m') | float) %} - {% set load5 = '{0:0.2f}'.format(states('sensor.average_load_5m') | float) %} - {% set load15 = '{0:0.2f}'.format(states('sensor.average_load_15m') | float) %} + {% set load1 = '{0:0.2f}'.format(states('sensor.load_1m') | float) %} + {% set load5 = '{0:0.2f}'.format(states('sensor.load_5m') | float) %} + {% set load15 = '{0:0.2f}'.format(states('sensor.load_15m') | float) %} {{ load1 }} {{ load5 }} {{ load15 }} @@ -272,6 +272,7 @@ # @see /appdaemon/dashboards/Status.dash # @see /groups/status.yaml # +# @link https://community.home-assistant.io/t/displaying-cpu-temperature-within-home-assistant/8641 # @link https://home-assistant.io/components/sensor.command_line/ # - platform: command_line @@ -284,32 +285,30 @@ # -# Database size +# File sizes # # @see /appdaemon/dashboards/Status.dash # @see /groups/status.yaml # -# @link https://community.home-assistant.io/t/recorder-purge-function/17154/12 -# @link https://home-assistant.io/components/sensor.command_line/ +# @link https://www.home-assistant.io/components/sensor.filesize/ # -- platform: command_line - name: Database Size - scan_interval: 600 - unit_of_measurement: 'MiB' - command: "du -m /config/home-assistant_v2.db | cut -f1" +- platform: filesize + file_paths: + - !secret filesize_database + - !secret filesize_log +- platform: template + sensors: + database_size: + friendly_name: Database Size + icon_template: mdi:database + unit_of_measurement: 'MiB' + value_template: >- + {{ states('sensor.homeassistant_v2db') | round }} -# -# Log file size -# -# @see /appdaemon/dashboards/Status.dash -# @see /groups/status.yaml -# -# @link https://community.home-assistant.io/t/recorder-purge-function/17154/12 -# @link https://home-assistant.io/components/sensor.command_line/ -# -- platform: command_line - name: Logfile Size - scan_interval: 600 - unit_of_measurement: 'KiB' - command: "du -k /config/home-assistant.log | cut -f1" + log_size: + friendly_name: Log Size + icon_template: mdi:history + unit_of_measurement: 'KiB' + value_template: >- + {{ (states.sensor.homeassistantlog.attributes.bytes / 1024) | round }} diff --git a/sensors/weather.yaml b/sensors/weather.yaml index 2487d2c..22f0fcf 100644 --- a/sensors/weather.yaml +++ b/sensors/weather.yaml @@ -339,6 +339,8 @@ wind_speed: friendly_name: Wind Speed unit_of_measurement: 'km/h' + friendly_name_template: >- + {{ states('sensor.wind_scale_friendly') }} value_template: >- {{ (states('sensor.dark_sky_wind_speed')|float * 3600 / 1000) | round(0) }} icon_template: >- @@ -410,7 +412,7 @@ value_template: >- {% set degrees = states('sensor.dark_sky_wind_bearing') | int %} {% set val = (degrees / 45) | int %} - {% set directions = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"] %} + {% set directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'] %} {{ directions[(val % 8)] }} @@ -420,14 +422,14 @@ {% set degrees = states('sensor.dark_sky_wind_bearing') | int %} {% set val = (degrees / 45) | int %} {% set directions = [ - "North", - "Northeast", - "East", - "Southeast", - "South", - "Southwest", - "West", - "Northwest" + 'North', + 'Northeast', + 'East', + 'Southeast', + 'South', + 'Southwest', + 'West', + 'Northwest' ] %} {{ directions[(val % 8)] }} @@ -437,7 +439,7 @@ value_template: >- {% set degrees = states('sensor.dark_sky_wind_bearing') | int %} {% set val = (degrees / 22.5 + 0.5) | int %} - {% set directions = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"] %} + {% set directions = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'] %} {{ directions[(val % 16)] }} @@ -447,22 +449,22 @@ {% set degrees = states('sensor.dark_sky_wind_bearing') | int %} {% set val = (degrees / 22.5 + 0.5) | int %} {% set directions = [ - "North", - "North-Northeast", - "Northeast", - "East-Northeast", - "East", - "East-Southeast", - "Southeast", - "South-Southeast", - "South", - "South-Southwest", - "Southwest", - "West-Southwest", - "West", - "West-Northwest", - "Northwest", - "North-Northwest" + 'North', + 'North-Northeast', + 'Northeast', + 'East-Northeast', + 'East', + 'East-Southeast', + 'Southeast', + 'South-Southeast', + 'South', + 'South-Southwest', + 'Southwest', + 'West-Southwest', + 'West', + 'West-Northwest', + 'Northwest', + 'North-Northwest' ] %} {{ directions[(val % 16)] }} diff --git a/switches/README.md b/switches/README.md index 56d157e..1635ba9 100644 --- a/switches/README.md +++ b/switches/README.md @@ -5,10 +5,6 @@ **[TP-Link smart plug mini outlets](http://www.tp-link.com/us/products/details/cat-5516_HS105.html)** are used to control dumb devices. -

- TP-Link HS105 Smart Wi-Fi Plug Mini outlets -

- They were first setup with the manufaturer's [Kasa app](https://www.tp-link.com/us/home-networking/smart-home/kasa.html). Then they were assigned static IP addresses in my router to avoid occasional drops due to DHCP renewal limbo. Still, some of them tend to drop off randomly if placed behind furniture or close to other wi-fi outlets/devices. I am considering moving to Zwave outlets or smart plugs to increase the reliabilty. diff --git a/themes/README.md b/themes/README.md index b2ac3fb..d0e6020 100644 --- a/themes/README.md +++ b/themes/README.md @@ -2,27 +2,93 @@ These CSS configurations serve to bonify the frontend's user interface and improve the user experience. +## Whole themes -## [`normal.yaml`](normal.yaml) theme +These full themes change the whole look of Home Assistant. + + +### [`🌞 ./normal.yaml`](normal.yaml) Contains minor improvements over Home Assistant's [default theme](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/resources/ha-style.html). +
+
+
+ Atmospheric Safety group +
+
+

Normal theme.

+
+
+
-## [`dark.yaml`](dark.yaml) theme + +### [`🌜 ./dark.yaml`](dark.yaml) Automtically set by [`/automations/theme_auto.yaml`](../automations/theme_auto.yaml) whenever `input_boolean.night_mode` is enabled. Based on [PmxMononight](https://community.home-assistant.io/t/share-your-themes/22018/38) by PhysicalMagic. +
+
+
+ Atmospheric Safety group (dark theme) +
+
+

Dark theme.

+
+
+
-## [`card-secondary-title.yaml`](card-secondary-title.yaml) theme -Used in [`/customize.yaml`](../customize.yaml) to replace a sensor's title with its dynamic `extra-data-template`. +## Card themes +These focused themes are used when modifying the display of specific sensors only. -## [`card-warning.yaml`](card-warning.yaml) theme -Used in [`/customize_glob.yaml`](../customize_glob.yaml) to highlight a sensor in yellow whenever its state is within a range that should be of interest. Using transprency, it looks good in both normal and dark themes. +### [`🥈 ./card-secondary-title.yaml`](card-secondary-title.yaml) +Used in [`/customize.yaml`](../customize.yaml) to replace a sensor's title with its dynamic `extra-data-template` when a component does not provide a `friendly_name_template` variable like the [template sensor](https://home-assistant.io/components/sensor.template/) does. -## [`card-critical.yaml`](card-critical.yaml) theme +
+
+
+ Secondary Title card +
+
+

Secondary Title card, used to replace the sensor name with the temperature's value.

+
+
+
+ + +### [`⚠ ./card-warning.yaml`](card-warning.yaml) + +Used in [`/customize_glob.yaml`](../customize_glob.yaml) to highlight a sensor in yellow whenever its state is within a range that should be of interest. Using transprency, it looks good in both normal and dark themes. -Used to highlight a sensor in red whenever its state is within a critical range that should command attention. Compatible with both normal and dark themes. +
+
+
+ Warning card + Warning card (dark theme) +
+
+

Warning card.

+
+
+
+ + +### [`🚨 ./card-critical.yaml`](card-critical.yaml) + +Used to highlight a sensor in red whenever its state is within a critical range that should command attention. Compatible with both normal and dark themes by also using transparency. + +
+
+
+ Critical card + Critical card (dark theme) +
+
+

Critical card.

+
+
+
diff --git a/themes/dark.yaml b/themes/dark.yaml index c81990a..1da534f 100644 --- a/themes/dark.yaml +++ b/themes/dark.yaml @@ -12,7 +12,7 @@ base-sat: '40%' #Controls the saturation of the theme (0%-100%) | 0%=Grey 100%=F # MyVar huesat: 'var(--base-hue), var(--base-sat),' # Primary Color -primary-color: 'hsl(var(--huesat) 20%)' +primary-color: 'hsl(var(--huesat) 25%)' # Backgrounds primary-background-color: 'var(--primary-color)' secondary-background-color: 'hsl(var(--huesat) 16%)' diff --git a/www/README.md b/www/README.md new file mode 100644 index 0000000..3f568ba --- /dev/null +++ b/www/README.md @@ -0,0 +1,52 @@ +# Public folder + +This is the default publicly accessible folder if Home Assistant. + + +## Contents + +### [`🌈 ./custom_ui/`](custom_ui) + +Where custom state card templates are stored. + +
+
+
+ Custom UI elements + Horizontal line state card +
+
+

./custom_ui/ state cards.

+
+
+
+ + +### [`🖼 ./images/`](images) + +
+
+
+ Technology diagram +
+
+

Various supporting ./images/.

+
+
+
+ + + +### [`📸 ./screenshots/`](screenshots) + +
+
+
+ Climate control group + Security Status group (dark theme) +
+
+

Sample ./screenshots/.

+
+
+
diff --git a/www/custom_ui/README.md b/www/custom_ui/README.md index b808e03..cc33841 100644 --- a/www/custom_ui/README.md +++ b/www/custom_ui/README.md @@ -1,33 +1,56 @@ # Custom UI state cards -These third-party state cards are used to adapt the looks of Home Assistant sensors for easier information consumption. +These state cards are used to adapt the looks of Home Assistant sensors for easier information consumption. +## Third-party state cards -## Custom UI elements +### [`🌈 ./state-card-custom-ui(-es5?).html(.gz?)`](state-card-custom-ui.html) **[Custom UI elements](https://github.com/andrey-git/home-assistant-custom-ui)** help improve the display of sensors and jazz up the interface a bit. -

- Custom UI + Value-only state card -

+
+
+
+ Weather group + Climate Control group +
+
+

Custom UI elements.

+
+
+
-## Horizontal line state card +### [`➖ ./state-card-hline(_es5?).html`](state-card-hline.html) **[Horizontal line state card](https://github.com/covrig/homeassistant-hline)** to visually separate long lists of sensors. -

- Custom UI + Horizontal line state card -

+
+
+
+ Horizontal line state card +
+
+

Horizontal line state card.

+
+
+
-## Value-only state card +### [`📝 ./state-card-value_only.html`](state-card-value_only.html) **[Value-only state card](https://community.home-assistant.io/t/display-only-text-in-card/20536/26)** for wordy sensor states. -

- Value-only state card -

+
+
+
+ Value-only state card +
+
+

Value-only state card.

+
+
+
## Customization diff --git a/www/custom_ui/state-card-custom-ui-es5.html b/www/custom_ui/state-card-custom-ui-es5.html index 8c44a3f..1771c99 100644 --- a/www/custom_ui/state-card-custom-ui-es5.html +++ b/www/custom_ui/state-card-custom-ui-es5.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/www/custom_ui/state-card-custom-ui-es5.html.gz b/www/custom_ui/state-card-custom-ui-es5.html.gz index 6e55704..313f734 100644 Binary files a/www/custom_ui/state-card-custom-ui-es5.html.gz and b/www/custom_ui/state-card-custom-ui-es5.html.gz differ diff --git a/www/custom_ui/state-card-custom-ui.html b/www/custom_ui/state-card-custom-ui.html index 79603fd..c089358 100644 --- a/www/custom_ui/state-card-custom-ui.html +++ b/www/custom_ui/state-card-custom-ui.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/www/custom_ui/state-card-custom-ui.html.gz b/www/custom_ui/state-card-custom-ui.html.gz index 15e3c69..fcdd747 100644 Binary files a/www/custom_ui/state-card-custom-ui.html.gz and b/www/custom_ui/state-card-custom-ui.html.gz differ diff --git a/www/images/README.md b/www/images/README.md new file mode 100644 index 0000000..d644b05 --- /dev/null +++ b/www/images/README.md @@ -0,0 +1,14 @@ +# Images + +Various supporting images useful in documenting this repository. + +
+
+
+ Technology diagram +
+
+

Technology Diagram (PNG, SVG). Made with Draw.io (XML source file).

+
+
+
diff --git a/www/images/technology-diagram.png b/www/images/technology-diagram.png new file mode 100644 index 0000000..f181306 Binary files /dev/null and b/www/images/technology-diagram.png differ diff --git a/www/images/technology-diagram.svg b/www/images/technology-diagram.svg new file mode 100644 index 0000000..620e907 --- /dev/null +++ b/www/images/technology-diagram.svg @@ -0,0 +1,2 @@ + +

René-Marc's Home Assistant Technology Diagram

release v2018.04.04
https://github.com/renemarc/home-assistant-config


[Not supported by viewer]
Hass.io
Hass.io<br>
MQTT
MQTT
Zwave
Bridge
[Not supported by viewer]
Weather Station
Weather Station
Aeotec Minimote
Aeotec Minimote
Lounge
Multisensor
Lounge<br>Multisensor
Washroom
Multisensor
Washroom<br>Multisensor
Front Door
Sensor
Front Door<br>Sensor
LAN
LAN
Frontend
Frontend
Cellphones
Cellphones
Kiosk
Kiosk
Airthings Wave
Airthings Wave
Internet
Internet
Kitchen Flic
Kitchen Flic
MiLight Hub
MiLight Hub
Sink
Sink
Countertop
Countertop
Lavatory
Lavatory
Microwave
Microwave
Island
Island
Bedroom Flic
Bedroom Flic
Window
Sensor
Window<br>Sensor
AcuRite Temp /
Humidity Sensor
AcuRite Temp /<br>Humidity Sensor
LIFX
Cloud Effects
LIFX<br>Cloud Effects
Nanoleaf
Aurora
Nanoleaf<br>Aurora
LIFX+
Lounge Spotlight
LIFX+<br>Lounge Spotlight
LIFX
Lounge Lamp
LIFX<br>Lounge Lamp
LIFX+
Front Porch
LIFX+ <br>Front Porch
LIFX
Bathroom Sconce
LIFX<br>Bathroom Sconce
LIFX+
Shower
LIFX+<br>Shower
LIFX Z
Bedroom
LIFX Z<br>Bedroom
LIFX Z
Middle
[Not supported by viewer]
LIFX Z
Lounge
LIFX Z<br>Lounge
TP-Link Outlet
TP-Link Outlet
Humidifier
Humidifier
Bedroom Fan
Bedroom Fan
TP-Link Outlet
TP-Link Outlet
Window Lights
Window Lights
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
TP-Link Outlet
Nightstand Lamp
Nightstand Lamp
Bedside Lights
Bedside Lights
Dehumidifier
Dehumidifier
Souvenirs Lights
Souvenirs Lights
LIFX Z
Underbed
LIFX Z<br>Underbed
LIFX Z
Headboard
LIFX Z<br>Headboard
Lightpack
Lightpack
Plex
Plex
Kodi
Kodi
HTPC
HTPC
Bluetooth
Bluetooth
RTL-SDR
RTL-SDR
planned
device
planned<br>device
\ No newline at end of file diff --git a/www/images/technology-diagram.xml b/www/images/technology-diagram.xml new file mode 100644 index 0000000..6319083 --- /dev/null +++ b/www/images/technology-diagram.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/www/screenshots/README.md b/www/screenshots/README.md new file mode 100644 index 0000000..c92f6da --- /dev/null +++ b/www/screenshots/README.md @@ -0,0 +1,438 @@ +# Screenshots + +Screenshots of UI elements features in this repository. A [screenshot making guide](#screenshot-making-guide) is available below. + + +## Cards + +
+
+
+ Warning card + Warning card (dark theme) +
+
+

Warning card.

+
+
+
+ +
+
+
+ Critical card + Critical card (dark theme) +
+
+

Critical card.

+
+
+
+ +
+
+
+ Secondary Title card +
+
+

Secondary Title card, used to replace the sensor name with the temperature's value.

+
+
+
+ +
+
+
+ Horizontal line state card +
+
+

Horizontal line state card.

+
+
+
+ +
+
+
+ LIFX+ card +
+
+

LIFX light control.

+
+
+
+ +
+
+
+ Lightpack card +
+
+

Lightpack control.

+
+
+
+ +
+
+
+ LimitlessLED card +
+
+

LimitlessLED control.

+
+
+
+ +
+
+
+ Nanoleaf Aurora card +
+
+

Nanoleaf Aurora control.

+
+
+
+ +
+
+
+ NOAA GeoColour satellite image + NOAA Water Vapour satellite image +
+
+

NOAA satellite images for North-America's East Coast.

+
+
+
+ + +## Area Groups + +
+
+
+ Kitchen group + Humidity group (dark theme) +
+
+

Area group.

+
+
+
+ +
+
+
+ Ceiling Wash lights group + Ceiling Wash lights group (dark theme) +
+
+

Ceiling Wash Light group.

+
+
+
+ +
+
+
+ Lounge group + Lounge group (dark theme) +
+
+

Lounge group.

+
+
+
+ +
+
+
+ Bedroom group + Bedroom group (dark theme) +
+
+

Bedroom group.

+
+
+
+ +
+
+
+ Washroom group + Washroom group (dark theme) +
+
+

Washroom group.

+
+
+
+ + +## Sensors Groups + +
+
+
+ Climate Control group + Climate Control group (dark theme) +
+
+

Climate Control group.

+
+
+
+
+ Humidity group + Humidity group (dark theme) +
+
+

Humidity group.

+
+
+
+
+ Temperature group + Temperature group (dark theme) +
+
+

Temperature group.

+
+
+
+ +
+
+
+ Battery Levels group + Battery Levels group (dark theme) +
+
+

Battery Levels group.

+
+
+
+ +
+
+
+ Atmospheric Safety group + Atmospheric Safety group (dark theme) +
+
+

Atmospheric Safety group.

+
+
+
+ +
+
+
+ Public Transit group + Public Transit group (dark theme) +
+
+

Public Transit group.

+
+
+
+ +
+
+
+ Network group + Network group (dark theme) +
+
+

Network group.

+
+
+
+ +
+
+
+ Security group + Security group (dark theme) +
+
+

Security group.

+
+
+
+ +
+
+
+ System group + System group (dark theme) +
+
+

System group.

+
+
+
+ +
+
+
+ Today's Weather group + Today's Weather group (dark theme) +
+
+ Weekly Forecast group + Weekly Forecast group (dark theme) +
+
+

Weather groups.

+
+
+
+ +
+
+
+ Calendar group + Calendar group (dark theme) +
+
+

Calendar group.

+
+
+
+ + +## Menus + +
+
+
+ Home +
+
+ Switchboard +
+
+ Weather +
+
+ Status +
+
+ Configuration +
+
+

Menus.

+
+
+
+ + +## Various + +
+
+
+ Actions group + Actions group (dark theme) +
+
+

Actions group.

+
+
+
+ +
+
+
+ Configuration group + Configuration group (dark theme) +
+
+

Configuration group.

+
+
+
+ +
+
+
+ Humidity notification + Humidity notification (dark theme) +
+
+

Notifications.

+
+
+
+ +
+
+
+ Modes group + Modes group (dark theme) +
+
+

Modes group.

+
+
+
+ +
+
+
+ Presence group + Presence group (dark theme) +
+
+

Presence group.

+
+
+
+ + +## Screenshot making guide + +These are the steps I used to make these screenshots and animated GIFs. The resulting web-optimized retina images are then embeded at half-width in the README.md files to make them look regular size, while keeping their sharpness on high-resolution screens withouth requiring too much bandwidth. These steps can also be performed on a regular-resolution screen, ideally while zoomed at %200. + + +### UI groups + +1. Take rough screenshot on retina/high-resolution screen. +2. Clean up screenshot in an image editor: + - Resize canvas to 650 pixels wide. + - Remove identifying information. + - Save in non-compressed format for reference (PNG, PSD, BMP...) +3. Export as web-optimized PNG. +4. Use [TinyPNG](https://tinypng.com) to compress web-optimized PNG further. + + +### HADashboard static image + +1. Take rough screenshot on retina/high-resolution screen. I used Firefox @ 80% zoom on a MacBook Pro 13". +2. Clean up screenshot in an image editor: + - Resize canvas to large-enough format, say 2000×1212. + - Uniformize elements with other screenshots. + - Remove identifying information. + - Replace copyrighted images with public domain placeholders. + - Save in non-compressed format for reference (PNG, PSD, BMP...) +3. Export as web-optimized PNG. +4. Use [TinyPNG](https://tinypng.com) to compress web-optimized PNG further. + + +### HADashboard animated GIF + +1. Take rough screenshot on retina/high-resolution screen. I used Firefox @ 80% zoom on a MacBook Pro 13". +2. Clean up screenshot in an image editor: + - Resize canvas to large-enough format, say 2000×1212. + - Uniformize elements with other screenshots. + - Remove identifying information. + - Replace copyrighted images with public domain placeholders. +3. Save as regular PNG. +4. Create animation with other PNGs using [PicGIF](http://www.pearlmountainsoft.com/picgif/) or other animated GIF-making software or web app. + - Export as non-optimzed GIF at x1080 resolution, say 1782x1080. +5. If needed, use [ImageMagick](https://www.imagemagick.org/) to make it loop indefinitely: + `mogrify -loop 0 dashboard-example-1080.gif` +6. Use [ezgif.com](https://ezgif.com/optimize) to compress animated GIF at 35%. diff --git a/www/screenshots/card-aurora.png b/www/screenshots/card-aurora.png new file mode 100644 index 0000000..d126cee Binary files /dev/null and b/www/screenshots/card-aurora.png differ diff --git a/www/screenshots/card-critical-dark.png b/www/screenshots/card-critical-dark.png new file mode 100644 index 0000000..f7117ae Binary files /dev/null and b/www/screenshots/card-critical-dark.png differ diff --git a/www/screenshots/card-critical.png b/www/screenshots/card-critical.png new file mode 100644 index 0000000..ed386e4 Binary files /dev/null and b/www/screenshots/card-critical.png differ diff --git a/www/screenshots/card-doomsday.png b/www/screenshots/card-doomsday.png new file mode 100644 index 0000000..7140959 Binary files /dev/null and b/www/screenshots/card-doomsday.png differ diff --git a/www/screenshots/card-horizontal-line.png b/www/screenshots/card-horizontal-line.png new file mode 100644 index 0000000..9ce9bbe Binary files /dev/null and b/www/screenshots/card-horizontal-line.png differ diff --git a/www/screenshots/card-kiosk.png b/www/screenshots/card-kiosk.png new file mode 100644 index 0000000..1db6413 Binary files /dev/null and b/www/screenshots/card-kiosk.png differ diff --git a/www/screenshots/card-lifx.png b/www/screenshots/card-lifx.png new file mode 100644 index 0000000..5422a8d Binary files /dev/null and b/www/screenshots/card-lifx.png differ diff --git a/www/screenshots/card-lightpack.png b/www/screenshots/card-lightpack.png new file mode 100644 index 0000000..2f34bf5 Binary files /dev/null and b/www/screenshots/card-lightpack.png differ diff --git a/www/screenshots/card-limitlessled.png b/www/screenshots/card-limitlessled.png new file mode 100644 index 0000000..3f8d6a0 Binary files /dev/null and b/www/screenshots/card-limitlessled.png differ diff --git a/www/screenshots/card-radar-rain.png b/www/screenshots/card-radar-rain.png new file mode 100644 index 0000000..879ce57 Binary files /dev/null and b/www/screenshots/card-radar-rain.png differ diff --git a/www/screenshots/card-radar-snow.png b/www/screenshots/card-radar-snow.png new file mode 100644 index 0000000..4eb7ed0 Binary files /dev/null and b/www/screenshots/card-radar-snow.png differ diff --git a/www/screenshots/card-satellite-geocolour.jpg b/www/screenshots/card-satellite-geocolour.jpg new file mode 100644 index 0000000..ad390f6 Binary files /dev/null and b/www/screenshots/card-satellite-geocolour.jpg differ diff --git a/www/screenshots/card-satellite-vapour.jpg b/www/screenshots/card-satellite-vapour.jpg new file mode 100644 index 0000000..a084952 Binary files /dev/null and b/www/screenshots/card-satellite-vapour.jpg differ diff --git a/www/screenshots/card-secondary.png b/www/screenshots/card-secondary.png new file mode 100644 index 0000000..27a36b7 Binary files /dev/null and b/www/screenshots/card-secondary.png differ diff --git a/www/screenshots/card-warning-dark.png b/www/screenshots/card-warning-dark.png new file mode 100644 index 0000000..ec0bd4a Binary files /dev/null and b/www/screenshots/card-warning-dark.png differ diff --git a/www/screenshots/card-warning.png b/www/screenshots/card-warning.png new file mode 100644 index 0000000..a476d55 Binary files /dev/null and b/www/screenshots/card-warning.png differ diff --git a/www/screenshots/dashboard-all.gif b/www/screenshots/dashboard-all.gif new file mode 100644 index 0000000..2018a30 Binary files /dev/null and b/www/screenshots/dashboard-all.gif differ diff --git a/www/screenshots/dashboard-main-1.png b/www/screenshots/dashboard-main-1.png new file mode 100644 index 0000000..a0eb87b Binary files /dev/null and b/www/screenshots/dashboard-main-1.png differ diff --git a/www/screenshots/dashboard-main-2.png b/www/screenshots/dashboard-main-2.png new file mode 100644 index 0000000..2d59eab Binary files /dev/null and b/www/screenshots/dashboard-main-2.png differ diff --git a/www/screenshots/dashboard-main-3.png b/www/screenshots/dashboard-main-3.png new file mode 100644 index 0000000..982d874 Binary files /dev/null and b/www/screenshots/dashboard-main-3.png differ diff --git a/www/screenshots/dashboard-main-4.png b/www/screenshots/dashboard-main-4.png new file mode 100644 index 0000000..141d954 Binary files /dev/null and b/www/screenshots/dashboard-main-4.png differ diff --git a/www/screenshots/dashboard-main.gif b/www/screenshots/dashboard-main.gif new file mode 100644 index 0000000..de4fbf2 Binary files /dev/null and b/www/screenshots/dashboard-main.gif differ diff --git a/www/screenshots/dashboard-status.png b/www/screenshots/dashboard-status.png new file mode 100644 index 0000000..afe6ee1 Binary files /dev/null and b/www/screenshots/dashboard-status.png differ diff --git a/www/screenshots/dashboard-switchboard-1.png b/www/screenshots/dashboard-switchboard-1.png new file mode 100644 index 0000000..59b97f6 Binary files /dev/null and b/www/screenshots/dashboard-switchboard-1.png differ diff --git a/www/screenshots/dashboard-switchboard-2.png b/www/screenshots/dashboard-switchboard-2.png new file mode 100644 index 0000000..a800b00 Binary files /dev/null and b/www/screenshots/dashboard-switchboard-2.png differ diff --git a/www/screenshots/dashboard-switchboard-3.png b/www/screenshots/dashboard-switchboard-3.png new file mode 100644 index 0000000..24259ab Binary files /dev/null and b/www/screenshots/dashboard-switchboard-3.png differ diff --git a/www/screenshots/dashboard-switchboard.gif b/www/screenshots/dashboard-switchboard.gif new file mode 100644 index 0000000..8a5ff08 Binary files /dev/null and b/www/screenshots/dashboard-switchboard.gif differ diff --git a/www/screenshots/dashboard-weather-1.png b/www/screenshots/dashboard-weather-1.png new file mode 100644 index 0000000..1322aa2 Binary files /dev/null and b/www/screenshots/dashboard-weather-1.png differ diff --git a/www/screenshots/dashboard-weather-2.png b/www/screenshots/dashboard-weather-2.png new file mode 100644 index 0000000..56be2d6 Binary files /dev/null and b/www/screenshots/dashboard-weather-2.png differ diff --git a/www/screenshots/dashboard-weather-3.png b/www/screenshots/dashboard-weather-3.png new file mode 100644 index 0000000..90b2f58 Binary files /dev/null and b/www/screenshots/dashboard-weather-3.png differ diff --git a/www/screenshots/dashboard-weather-4.png b/www/screenshots/dashboard-weather-4.png new file mode 100644 index 0000000..54a8203 Binary files /dev/null and b/www/screenshots/dashboard-weather-4.png differ diff --git a/www/screenshots/dashboard-weather-5.png b/www/screenshots/dashboard-weather-5.png new file mode 100644 index 0000000..0ed7168 Binary files /dev/null and b/www/screenshots/dashboard-weather-5.png differ diff --git a/www/screenshots/dashboard-weather-6.png b/www/screenshots/dashboard-weather-6.png new file mode 100644 index 0000000..839b7c1 Binary files /dev/null and b/www/screenshots/dashboard-weather-6.png differ diff --git a/www/screenshots/dashboard-weather.gif b/www/screenshots/dashboard-weather.gif new file mode 100644 index 0000000..a97a8e7 Binary files /dev/null and b/www/screenshots/dashboard-weather.gif differ diff --git a/www/screenshots/group-actions-dark.png b/www/screenshots/group-actions-dark.png new file mode 100644 index 0000000..d1a4b38 Binary files /dev/null and b/www/screenshots/group-actions-dark.png differ diff --git a/www/screenshots/group-actions.png b/www/screenshots/group-actions.png new file mode 100644 index 0000000..b98a2da Binary files /dev/null and b/www/screenshots/group-actions.png differ diff --git a/www/screenshots/group-atmosphere-dark.png b/www/screenshots/group-atmosphere-dark.png new file mode 100644 index 0000000..ee03aa1 Binary files /dev/null and b/www/screenshots/group-atmosphere-dark.png differ diff --git a/www/screenshots/group-atmosphere.png b/www/screenshots/group-atmosphere.png new file mode 100644 index 0000000..ec9ce0e Binary files /dev/null and b/www/screenshots/group-atmosphere.png differ diff --git a/www/screenshots/group-battery-dark.png b/www/screenshots/group-battery-dark.png new file mode 100644 index 0000000..1f28f3f Binary files /dev/null and b/www/screenshots/group-battery-dark.png differ diff --git a/www/screenshots/group-battery.png b/www/screenshots/group-battery.png new file mode 100644 index 0000000..2f1338a Binary files /dev/null and b/www/screenshots/group-battery.png differ diff --git a/www/screenshots/group-bedroom-dark.png b/www/screenshots/group-bedroom-dark.png new file mode 100644 index 0000000..f7a679e Binary files /dev/null and b/www/screenshots/group-bedroom-dark.png differ diff --git a/www/screenshots/group-bedroom.png b/www/screenshots/group-bedroom.png new file mode 100644 index 0000000..7d1b732 Binary files /dev/null and b/www/screenshots/group-bedroom.png differ diff --git a/www/screenshots/group-calendar-dark.png b/www/screenshots/group-calendar-dark.png new file mode 100644 index 0000000..1fc30fa Binary files /dev/null and b/www/screenshots/group-calendar-dark.png differ diff --git a/www/screenshots/group-calendar.png b/www/screenshots/group-calendar.png new file mode 100644 index 0000000..d15fcfe Binary files /dev/null and b/www/screenshots/group-calendar.png differ diff --git a/www/screenshots/group-ceiling-dark.png b/www/screenshots/group-ceiling-dark.png new file mode 100644 index 0000000..4c99e98 Binary files /dev/null and b/www/screenshots/group-ceiling-dark.png differ diff --git a/www/screenshots/group-ceiling.png b/www/screenshots/group-ceiling.png new file mode 100644 index 0000000..aa86c22 Binary files /dev/null and b/www/screenshots/group-ceiling.png differ diff --git a/www/screenshots/group-climate-dark.png b/www/screenshots/group-climate-dark.png new file mode 100644 index 0000000..3127926 Binary files /dev/null and b/www/screenshots/group-climate-dark.png differ diff --git a/www/screenshots/group-climate.png b/www/screenshots/group-climate.png new file mode 100644 index 0000000..b25ec93 Binary files /dev/null and b/www/screenshots/group-climate.png differ diff --git a/www/screenshots/group-configuration-dark.png b/www/screenshots/group-configuration-dark.png new file mode 100644 index 0000000..ec6e07f Binary files /dev/null and b/www/screenshots/group-configuration-dark.png differ diff --git a/www/screenshots/group-configuration.png b/www/screenshots/group-configuration.png new file mode 100644 index 0000000..b14125c Binary files /dev/null and b/www/screenshots/group-configuration.png differ diff --git a/www/screenshots/group-forecast-dark.png b/www/screenshots/group-forecast-dark.png new file mode 100644 index 0000000..d7a5d25 Binary files /dev/null and b/www/screenshots/group-forecast-dark.png differ diff --git a/www/screenshots/group-forecast.png b/www/screenshots/group-forecast.png new file mode 100644 index 0000000..13b179d Binary files /dev/null and b/www/screenshots/group-forecast.png differ diff --git a/www/screenshots/group-humidity-dark.png b/www/screenshots/group-humidity-dark.png new file mode 100644 index 0000000..1a4d415 Binary files /dev/null and b/www/screenshots/group-humidity-dark.png differ diff --git a/www/screenshots/group-humidity.png b/www/screenshots/group-humidity.png new file mode 100644 index 0000000..abd0f13 Binary files /dev/null and b/www/screenshots/group-humidity.png differ diff --git a/www/screenshots/group-kitchen-dark.png b/www/screenshots/group-kitchen-dark.png new file mode 100644 index 0000000..b5e64dd Binary files /dev/null and b/www/screenshots/group-kitchen-dark.png differ diff --git a/www/screenshots/group-kitchen.png b/www/screenshots/group-kitchen.png new file mode 100644 index 0000000..8fd5a68 Binary files /dev/null and b/www/screenshots/group-kitchen.png differ diff --git a/www/screenshots/group-lounge-dark.png b/www/screenshots/group-lounge-dark.png new file mode 100644 index 0000000..a02e44d Binary files /dev/null and b/www/screenshots/group-lounge-dark.png differ diff --git a/www/screenshots/group-lounge.png b/www/screenshots/group-lounge.png new file mode 100644 index 0000000..17bb054 Binary files /dev/null and b/www/screenshots/group-lounge.png differ diff --git a/www/screenshots/group-modes-dark.png b/www/screenshots/group-modes-dark.png new file mode 100644 index 0000000..63d88d5 Binary files /dev/null and b/www/screenshots/group-modes-dark.png differ diff --git a/www/screenshots/group-modes.png b/www/screenshots/group-modes.png new file mode 100644 index 0000000..6da5841 Binary files /dev/null and b/www/screenshots/group-modes.png differ diff --git a/www/screenshots/group-network-dark.png b/www/screenshots/group-network-dark.png new file mode 100644 index 0000000..ea3332d Binary files /dev/null and b/www/screenshots/group-network-dark.png differ diff --git a/www/screenshots/group-network.png b/www/screenshots/group-network.png new file mode 100644 index 0000000..832abc1 Binary files /dev/null and b/www/screenshots/group-network.png differ diff --git a/www/screenshots/group-presence-dark.png b/www/screenshots/group-presence-dark.png new file mode 100644 index 0000000..197358b Binary files /dev/null and b/www/screenshots/group-presence-dark.png differ diff --git a/www/screenshots/group-presence.png b/www/screenshots/group-presence.png new file mode 100644 index 0000000..ccc7128 Binary files /dev/null and b/www/screenshots/group-presence.png differ diff --git a/www/screenshots/group-security-dark.png b/www/screenshots/group-security-dark.png new file mode 100644 index 0000000..9673bff Binary files /dev/null and b/www/screenshots/group-security-dark.png differ diff --git a/www/screenshots/group-security.png b/www/screenshots/group-security.png new file mode 100644 index 0000000..6f0bb1d Binary files /dev/null and b/www/screenshots/group-security.png differ diff --git a/www/screenshots/group-system-dark.png b/www/screenshots/group-system-dark.png new file mode 100644 index 0000000..6992075 Binary files /dev/null and b/www/screenshots/group-system-dark.png differ diff --git a/www/screenshots/group-system.png b/www/screenshots/group-system.png new file mode 100644 index 0000000..c08a47d Binary files /dev/null and b/www/screenshots/group-system.png differ diff --git a/www/screenshots/group-temperature-dark.png b/www/screenshots/group-temperature-dark.png new file mode 100644 index 0000000..228c218 Binary files /dev/null and b/www/screenshots/group-temperature-dark.png differ diff --git a/www/screenshots/group-temperature.png b/www/screenshots/group-temperature.png new file mode 100644 index 0000000..6d46389 Binary files /dev/null and b/www/screenshots/group-temperature.png differ diff --git a/www/screenshots/group-transit-dark.png b/www/screenshots/group-transit-dark.png new file mode 100644 index 0000000..084042e Binary files /dev/null and b/www/screenshots/group-transit-dark.png differ diff --git a/www/screenshots/group-transit.png b/www/screenshots/group-transit.png new file mode 100644 index 0000000..d92431a Binary files /dev/null and b/www/screenshots/group-transit.png differ diff --git a/www/screenshots/group-washroom-dark.png b/www/screenshots/group-washroom-dark.png new file mode 100644 index 0000000..7c0ca01 Binary files /dev/null and b/www/screenshots/group-washroom-dark.png differ diff --git a/www/screenshots/group-washroom.png b/www/screenshots/group-washroom.png new file mode 100644 index 0000000..27f9bf7 Binary files /dev/null and b/www/screenshots/group-washroom.png differ diff --git a/www/screenshots/group-weather-dark.png b/www/screenshots/group-weather-dark.png new file mode 100644 index 0000000..62f28bb Binary files /dev/null and b/www/screenshots/group-weather-dark.png differ diff --git a/www/screenshots/group-weather.png b/www/screenshots/group-weather.png new file mode 100644 index 0000000..e6de3e7 Binary files /dev/null and b/www/screenshots/group-weather.png differ diff --git a/www/screenshots/menu-configuration.png b/www/screenshots/menu-configuration.png new file mode 100644 index 0000000..6ea0503 Binary files /dev/null and b/www/screenshots/menu-configuration.png differ diff --git a/www/screenshots/menu-home.png b/www/screenshots/menu-home.png new file mode 100644 index 0000000..36a14bb Binary files /dev/null and b/www/screenshots/menu-home.png differ diff --git a/www/screenshots/menu-status.png b/www/screenshots/menu-status.png new file mode 100644 index 0000000..0069983 Binary files /dev/null and b/www/screenshots/menu-status.png differ diff --git a/www/screenshots/menu-switchboard.png b/www/screenshots/menu-switchboard.png new file mode 100644 index 0000000..99cf1d9 Binary files /dev/null and b/www/screenshots/menu-switchboard.png differ diff --git a/www/screenshots/menu-weather.png b/www/screenshots/menu-weather.png new file mode 100644 index 0000000..ae4551e Binary files /dev/null and b/www/screenshots/menu-weather.png differ diff --git a/www/screenshots/notification-humidity-dark.png b/www/screenshots/notification-humidity-dark.png new file mode 100644 index 0000000..ee143e1 Binary files /dev/null and b/www/screenshots/notification-humidity-dark.png differ diff --git a/www/screenshots/notification-humidity.png b/www/screenshots/notification-humidity.png new file mode 100644 index 0000000..7380f7a Binary files /dev/null and b/www/screenshots/notification-humidity.png differ diff --git a/www/screenshots/widget-entitycamera.gif b/www/screenshots/widget-entitycamera.gif new file mode 100644 index 0000000..05d6971 Binary files /dev/null and b/www/screenshots/widget-entitycamera.gif differ diff --git a/www/screenshots/widget-entitysensor.png b/www/screenshots/widget-entitysensor.png new file mode 100644 index 0000000..bd6d4a7 Binary files /dev/null and b/www/screenshots/widget-entitysensor.png differ diff --git a/www/screenshots/widget-iconsensor.png b/www/screenshots/widget-iconsensor.png new file mode 100644 index 0000000..7cc199b Binary files /dev/null and b/www/screenshots/widget-iconsensor.png differ diff --git a/www/screenshots/widget-input_select.png b/www/screenshots/widget-input_select.png new file mode 100644 index 0000000..57c76a9 Binary files /dev/null and b/www/screenshots/widget-input_select.png differ diff --git a/www/screenshots/widget-multisensor.png b/www/screenshots/widget-multisensor.png new file mode 100644 index 0000000..07993f1 Binary files /dev/null and b/www/screenshots/widget-multisensor.png differ diff --git a/zones/README.md b/zones/README.md deleted file mode 100644 index cd6aba8..0000000 --- a/zones/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Zones - -Used for eventual automations based on user distance from key locations. diff --git a/zones/home.yaml b/zones/home.yaml deleted file mode 100644 index f024bda..0000000 --- a/zones/home.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# -# Home zone -# -# @link https://home-assistant.io/components/zone/ -# -name: Home -latitude: !secret zone_home_latitude -longitude: !secret zone_home_longitude -radius: 100 -icon: mdi:home-heart diff --git a/zones/terminal.yaml b/zones/terminal.yaml deleted file mode 100644 index dadf3e0..0000000 --- a/zones/terminal.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# -# Bus terminal zone -# -# @link https://home-assistant.io/components/zone/ -# -name: Bus Terminal -latitude: !secret zone_terminal_latitude -longitude: !secret zone_terminal_longitude -radius: 500 -icon: mdi:subway diff --git a/zones/work.yaml b/zones/work.yaml deleted file mode 100644 index 56218fa..0000000 --- a/zones/work.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# -# Work zone -# -# @link https://home-assistant.io/components/zone/ -# -name: Work -latitude: !secret zone_work_latitude -longitude: !secret zone_work_longitude -radius: 500 -icon: mdi:worker