From 60ff7bc076e3dd0d1cf9e717f36de1b7122c48c4 Mon Sep 17 00:00:00 2001 From: 31c0fe9c6dbd74bcdde92e1d2aaa03e1d272f75f Date: Wed, 11 May 2022 16:41:13 +1000 Subject: [PATCH] Home Assistant Git Exporter --- .gitignore | 3 + addons/243ffc37_git-exporter.yaml | 44 + addons/243ffc37_rsync.yaml | 6 + addons/243ffc37_syncthing.yaml | 1 + addons/45df7312_zigbee2mqtt.yaml | 9 + addons/77b2833f_timescaledb.yaml | 11 + addons/9c51689a_pgweb.yaml | 1 + addons/a0d7b954_esphome.yaml | 1 + addons/a0d7b954_nodered.yaml | 16 + addons/a0d7b954_sqlite-web.yaml | 1 + addons/a0d7b954_zerotier.yaml | 3 + .../cebe7a76_hassio_google_drive_backup.yaml | 4 + addons/core_configurator.yaml | 9 + addons/core_mosquitto.yaml | 13 + addons/core_samba.yaml | 13 + addons/core_ssh.yaml | 12 + addons/repositories.yaml | 60 ++ config/.HA_VERSION | 1 + config/TODO.md | 10 + config/automations.yaml | 59 ++ .../automation/EPMatt/ikea_e1524_e1810.yaml | 811 ++++++++++++++++++ ...able_vacuum_camera_update_when_docked.yaml | 52 ++ .../homeassistant/motion_light.yaml | 50 ++ .../confirmable_notification.yaml | 84 ++ config/configuration.yaml | 53 ++ config/customize.yaml | 8 + config/groups.yaml | 0 config/packages/3d_printing.yaml | 54 ++ config/packages/ble_gateway.yaml | 63 ++ config/packages/debug.yaml | 33 + config/packages/electricity.yaml | 8 + config/packages/export.yaml | 11 + config/packages/gate.yaml | 123 +++ config/packages/grow.yaml | 420 +++++++++ config/packages/home.yaml | 181 ++++ config/packages/media_centre.yaml | 390 +++++++++ config/packages/media_server.yaml | 23 + config/packages/misc.yaml | 60 ++ config/packages/offices.yaml | 71 ++ config/packages/presence.yaml | 169 ++++ config/packages/vacuum.yaml | 25 + config/packages/work.yaml | 34 + config/scenes.yaml | 1 + config/scripts.yaml | 48 ++ config/watchman_report.txt | 98 +++ config/webostv.conf | Bin 0 -> 12288 bytes config/zigbee2mqtt/configuration.yaml | 1 + config/zigbee2mqtt/state.json | 1 + esphome/.gitignore | 11 + esphome/athom-plug-55869a.yaml | 10 + esphome/athom-plug-5586a8.yaml | 10 + esphome/athom-plug-ce0b40.yaml | 10 + esphome/athom-plug-ceed51.yaml | 11 + esphome/athom-plug-cf4329.yaml | 10 + esphome/athom-smart-plug-v2-3fea2b.yaml | 14 + esphome/athom-smart-plug-v2-3feafe.yaml | 13 + esphome/athom-smart-plug-v2-3fec6e.yaml | 14 + esphome/athom-smart-plug-v2-3ff2fc.yaml | 13 + esphome/athom-smart-plug-v2-3ff494.yaml | 13 + esphome/ble-gateway-1.yaml | 18 + esphome/ble-gateway-2.yaml | 209 +++++ esphome/ble-gateway-3.yaml | 14 + esphome/common/athom-plug.yaml | 117 +++ esphome/common/base.yaml | 63 ++ esphome/common/ble-gateway.yaml | 26 + esphome/common/kogan-power-strip.yaml | 105 +++ esphome/common/wifi.yaml | 12 + esphome/front-gate.yaml | 134 +++ esphome/power-strip-1686ec.yaml | 17 + esphome/power-strip-1687f5.yaml | 17 + lovelace/lovelace.3d_printing.yaml | 162 ++++ lovelace/lovelace.bos_office.yaml | 45 + lovelace/lovelace.lovelace_gardens.yaml | 623 ++++++++++++++ lovelace/lovelace.lovelace_sensors.yaml | 336 ++++++++ lovelace/lovelace.lovelace_servers.yaml | 326 +++++++ lovelace/lovelace.lovelace_shed.yaml | 3 + lovelace/lovelace.yaml | 712 +++++++++++++++ lovelace/lovelace_dashboards.yaml | 43 + lovelace/lovelace_resources.yaml | 118 +++ node-red/flows.json | 1 + node-red/settings.js | 193 +++++ 81 files changed, 6572 insertions(+) create mode 100644 addons/243ffc37_git-exporter.yaml create mode 100644 addons/243ffc37_rsync.yaml create mode 100644 addons/243ffc37_syncthing.yaml create mode 100644 addons/45df7312_zigbee2mqtt.yaml create mode 100644 addons/77b2833f_timescaledb.yaml create mode 100644 addons/9c51689a_pgweb.yaml create mode 100644 addons/a0d7b954_esphome.yaml create mode 100644 addons/a0d7b954_nodered.yaml create mode 100644 addons/a0d7b954_sqlite-web.yaml create mode 100644 addons/a0d7b954_zerotier.yaml create mode 100644 addons/cebe7a76_hassio_google_drive_backup.yaml create mode 100644 addons/core_configurator.yaml create mode 100644 addons/core_mosquitto.yaml create mode 100644 addons/core_samba.yaml create mode 100644 addons/core_ssh.yaml create mode 100644 addons/repositories.yaml create mode 100644 config/.HA_VERSION create mode 100644 config/TODO.md create mode 100644 config/automations.yaml create mode 100644 config/blueprints/automation/EPMatt/ikea_e1524_e1810.yaml create mode 100644 config/blueprints/automation/PiotrMachowski/disable_vacuum_camera_update_when_docked.yaml create mode 100644 config/blueprints/automation/homeassistant/motion_light.yaml create mode 100644 config/blueprints/script/homeassistant/confirmable_notification.yaml create mode 100644 config/configuration.yaml create mode 100644 config/customize.yaml create mode 100644 config/groups.yaml create mode 100644 config/packages/3d_printing.yaml create mode 100644 config/packages/ble_gateway.yaml create mode 100644 config/packages/debug.yaml create mode 100644 config/packages/electricity.yaml create mode 100644 config/packages/export.yaml create mode 100644 config/packages/gate.yaml create mode 100644 config/packages/grow.yaml create mode 100644 config/packages/home.yaml create mode 100644 config/packages/media_centre.yaml create mode 100644 config/packages/media_server.yaml create mode 100644 config/packages/misc.yaml create mode 100644 config/packages/offices.yaml create mode 100644 config/packages/presence.yaml create mode 100644 config/packages/vacuum.yaml create mode 100644 config/packages/work.yaml create mode 100644 config/scenes.yaml create mode 100644 config/scripts.yaml create mode 100644 config/watchman_report.txt create mode 100644 config/webostv.conf create mode 100644 config/zigbee2mqtt/configuration.yaml create mode 100644 config/zigbee2mqtt/state.json create mode 100644 esphome/.gitignore create mode 100644 esphome/athom-plug-55869a.yaml create mode 100644 esphome/athom-plug-5586a8.yaml create mode 100644 esphome/athom-plug-ce0b40.yaml create mode 100644 esphome/athom-plug-ceed51.yaml create mode 100644 esphome/athom-plug-cf4329.yaml create mode 100644 esphome/athom-smart-plug-v2-3fea2b.yaml create mode 100644 esphome/athom-smart-plug-v2-3feafe.yaml create mode 100644 esphome/athom-smart-plug-v2-3fec6e.yaml create mode 100644 esphome/athom-smart-plug-v2-3ff2fc.yaml create mode 100644 esphome/athom-smart-plug-v2-3ff494.yaml create mode 100644 esphome/ble-gateway-1.yaml create mode 100644 esphome/ble-gateway-2.yaml create mode 100644 esphome/ble-gateway-3.yaml create mode 100644 esphome/common/athom-plug.yaml create mode 100644 esphome/common/base.yaml create mode 100644 esphome/common/ble-gateway.yaml create mode 100644 esphome/common/kogan-power-strip.yaml create mode 100644 esphome/common/wifi.yaml create mode 100644 esphome/front-gate.yaml create mode 100644 esphome/power-strip-1686ec.yaml create mode 100644 esphome/power-strip-1687f5.yaml create mode 100644 lovelace/lovelace.3d_printing.yaml create mode 100644 lovelace/lovelace.bos_office.yaml create mode 100644 lovelace/lovelace.lovelace_gardens.yaml create mode 100644 lovelace/lovelace.lovelace_sensors.yaml create mode 100644 lovelace/lovelace.lovelace_servers.yaml create mode 100644 lovelace/lovelace.lovelace_shed.yaml create mode 100644 lovelace/lovelace.yaml create mode 100644 lovelace/lovelace_dashboards.yaml create mode 100644 lovelace/lovelace_resources.yaml create mode 100644 node-red/flows.json create mode 100644 node-red/settings.js diff --git a/.gitignore b/.gitignore index 3ad3b42..54bad01 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ log.txt deps/ tts/ + +aircast.xml +airsonos.xml diff --git a/addons/243ffc37_git-exporter.yaml b/addons/243ffc37_git-exporter.yaml new file mode 100644 index 0000000..b636e35 --- /dev/null +++ b/addons/243ffc37_git-exporter.yaml @@ -0,0 +1,44 @@ +check: + check_for_ips: false + check_for_secrets: true + enabled: false +dry_run: false +exclude: +- '*.db' +- '*.log*' +- __pycache__ +- ._* +- .DS_Store +- deps/ +- known_devices.yaml +- tts/ +- '*.tmp' +- '*.swp' +- '*.bak' +- .nvimlog +- build/ +- '*.fault' +- secrets.yaml +- esphome/common/secrets.yaml +- .stversions +- custom_components +- .st* +- ~*-*.yaml +- log.text +- /www/ +- .local/ +- .vscode/ +- .cache/ +- .bash_history +export: + addons: true + esphome: true + lovelace: true + node_red: true +repository: + branch_name: main + commit_message: Home Assistant Git Exporter + password: '!secret git_export_password' + pull_before_push: true + url: '!secret git_export_url' + username: '!secret git_export_password' diff --git a/addons/243ffc37_rsync.yaml b/addons/243ffc37_rsync.yaml new file mode 100644 index 0000000..f2a39cb --- /dev/null +++ b/addons/243ffc37_rsync.yaml @@ -0,0 +1,6 @@ +folders: +- /config +private_key_file: /ssl/rsync/id_rsa +remote_folder: /home/user +remote_host: '' +username: user diff --git a/addons/243ffc37_syncthing.yaml b/addons/243ffc37_syncthing.yaml new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/addons/243ffc37_syncthing.yaml @@ -0,0 +1 @@ +{} diff --git a/addons/45df7312_zigbee2mqtt.yaml b/addons/45df7312_zigbee2mqtt.yaml new file mode 100644 index 0000000..ad71225 --- /dev/null +++ b/addons/45df7312_zigbee2mqtt.yaml @@ -0,0 +1,9 @@ +data_path: /config/zigbee2mqtt +mqtt: {} +serial: {} +socat: + enabled: false + log: false + master: pty,raw,echo=0,link=/tmp/ttyZ2M,mode=777 + options: -d -d + slave: tcp-listen:8485,keepalive,nodelay,reuseaddr,keepidle=1,keepintvl=1,keepcnt=5 diff --git a/addons/77b2833f_timescaledb.yaml b/addons/77b2833f_timescaledb.yaml new file mode 100644 index 0000000..bf3bc8b --- /dev/null +++ b/addons/77b2833f_timescaledb.yaml @@ -0,0 +1,11 @@ +databases: +- homeassistant +init_commands: [] +max_connections: 20 +system_packages: [] +timescale_enabled: +- homeassistant +timescaledb: + maxcpus: '4' + maxmemory: 512MB + telemetry: basic diff --git a/addons/9c51689a_pgweb.yaml b/addons/9c51689a_pgweb.yaml new file mode 100644 index 0000000..30630e7 --- /dev/null +++ b/addons/9c51689a_pgweb.yaml @@ -0,0 +1 @@ +db: '!secret recorder_db' diff --git a/addons/a0d7b954_esphome.yaml b/addons/a0d7b954_esphome.yaml new file mode 100644 index 0000000..6e29422 --- /dev/null +++ b/addons/a0d7b954_esphome.yaml @@ -0,0 +1 @@ +leave_front_door_open: true diff --git a/addons/a0d7b954_nodered.yaml b/addons/a0d7b954_nodered.yaml new file mode 100644 index 0000000..3bb2e7f --- /dev/null +++ b/addons/a0d7b954_nodered.yaml @@ -0,0 +1,16 @@ +certfile: fullchain.pem +credential_secret: '!secret nodered_secret' +dark_mode: false +http_node: + password: '' + username: '' +http_static: + password: '' + username: '' +init_commands: [] +keyfile: privkey.pem +npm_packages: [] +require_ssl: false +ssl: false +system_packages: [] +theme: default diff --git a/addons/a0d7b954_sqlite-web.yaml b/addons/a0d7b954_sqlite-web.yaml new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/addons/a0d7b954_sqlite-web.yaml @@ -0,0 +1 @@ +{} diff --git a/addons/a0d7b954_zerotier.yaml b/addons/a0d7b954_zerotier.yaml new file mode 100644 index 0000000..087939f --- /dev/null +++ b/addons/a0d7b954_zerotier.yaml @@ -0,0 +1,3 @@ +api_auth_token: G5XtXp31iwh1Xl0yfaGaXc317Oo9JgVB +networks: +- 17d709436c21ca93 diff --git a/addons/cebe7a76_hassio_google_drive_backup.yaml b/addons/cebe7a76_hassio_google_drive_backup.yaml new file mode 100644 index 0000000..f489216 --- /dev/null +++ b/addons/cebe7a76_hassio_google_drive_backup.yaml @@ -0,0 +1,4 @@ +days_between_backups: 3 +max_backups_in_google_drive: 4 +max_backups_in_ha: 4 +send_error_reports: true diff --git a/addons/core_configurator.yaml b/addons/core_configurator.yaml new file mode 100644 index 0000000..9ff6ec3 --- /dev/null +++ b/addons/core_configurator.yaml @@ -0,0 +1,9 @@ +dirsfirst: false +enforce_basepath: true +git: true +ignore_pattern: +- __pycache__ +- .cloud +- .storage +- deps +ssh_keys: [] diff --git a/addons/core_mosquitto.yaml b/addons/core_mosquitto.yaml new file mode 100644 index 0000000..402d11a --- /dev/null +++ b/addons/core_mosquitto.yaml @@ -0,0 +1,13 @@ +certfile: fullchain.pem +customize: + active: false + folder: mosquitto +keyfile: privkey.pem +logins: +- password: '!secret mosquitto_espresense_password' + username: espresense +- password: '!secret mosquitto_esphome_password' + username: esphome +- password: '!secret mosquitto_zigbee2mqtt_password' + username: zigbee2mqtt +require_certificate: false diff --git a/addons/core_samba.yaml b/addons/core_samba.yaml new file mode 100644 index 0000000..472d1d1 --- /dev/null +++ b/addons/core_samba.yaml @@ -0,0 +1,13 @@ +allow_hosts: +- '!secret lan_subnet' +- '!secret docker_subnet' +compatibility_mode: false +password: '!secret samba_password' +username: '!secret samba_username' +veto_files: +- ._* +- .DS_Store +- Thumbs.db +- icon? +- .Trashes +workgroup: WORKGROUP diff --git a/addons/core_ssh.yaml b/addons/core_ssh.yaml new file mode 100644 index 0000000..977d107 --- /dev/null +++ b/addons/core_ssh.yaml @@ -0,0 +1,12 @@ +apks: +- neovim +- postgresql-client +- bat +authorized_keys: +- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO3TLYeC/VkgBdsabbhRDG5mdTgIsjvE2046Pir4DQFb +- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILIusX84DqZiOvTKgjD481KIF5gH5XZcC26AIo4y/E9M +- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCequm1RHBiWwfCRPcKc+I8ptsIwj5dW3O9ETbKbnkqkZv6Ent2nm5zVYK7YdmS2IEhcZtCZVmOOc+m0xH4/x5aRH7HnUtP1De72HTrR82yvOMa4uOsgF73Sb3Fo94UXT+9C3jdWiemiNVB87szi6RQxRTRxcEsX76r6ViMSigEPAviuNWiGMbmw+5hVJhVq4Vv8C6wN3C7F2GrKkSuorr5e7oXluaSEg5rgusuQn637dSK1kbJSeda4qsdaOj5zrOPYWxT/HkZLvAOnwz1XuLl+uLQVrkikFp3mXrYT8jarbt6q3e95JpA2SQJVZNpCL55akUUVEr7FocxOmGS7awprYI3PDryCbmTHp64mx/6XzhRDhYYnauKMu1nnU3pasCj2kCaFg1k9Ficq9o6yWpRGxvUb5ZPAE06YlTwXeEHFATIA/GXdi33G60Zjd0kmfEjbjOOihU+Oxvg7vCzFVHsg2qL5/8KpVHP7kpkYANgjjSvZE3zl2IKOMLvlBslpmcYX/GN/J5Ln0BSi1lw0e51PQePhVZC6Wqt1jQ2NMQ9BJRFWSNAraEeU2Df+GlJUF2yoDU0vVpSYETTpTZt6l2u/L3h+/YElWpZNAba1Y7EqvXgKF9C/DCZteAxXXcOmdNeUYrJnKD2er9vG5JqN0R5Fvws77R+fSc6ldrH1Ft7EQ== +- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJykg+5TulcwmeKFYSjZmnrL5/Fo4kWmOV1fAyt41Evh +password: '' +server: + tcp_forwarding: false diff --git a/addons/repositories.yaml b/addons/repositories.yaml new file mode 100644 index 0000000..2edb662 --- /dev/null +++ b/addons/repositories.yaml @@ -0,0 +1,60 @@ +Expaso Home Assistant Add-Ons: + maintainer: Hans van Essen + slug: 77b2833f + source: https://github.com/Expaso/hassos-addons +Frigate hass.io addons: + maintainer: blakeblackshear + slug: ccab4aaf + source: https://github.com/blakeblackshear/frigate-hass-addons +HA Add-ons by alexbelgium: + maintainer: alexbelgium + slug: db21ed7f + source: https://github.com/alexbelgium/hassio-addons +Hass.io add-ons by Nicolai: + maintainer: Nicolai Bjerre Pedersen + slug: 0844df1a + source: https://github.com/overkill32/hassio-addons +'Home Assistant Add-on: Zigbee2mqtt': + maintainer: Daniel Welch + slug: 45df7312 + source: https://github.com/zigbee2mqtt/hassio-zigbee2mqtt +Home Assistant Community Add-ons: + maintainer: Franck Nijhof + slug: a0d7b954 + source: https://github.com/hassio-addons/repository +Home Assistant Google Drive Backup Repository: + maintainer: Stephen Beechen + slug: cebe7a76 + source: https://github.com/sabeechen/hassio-google-drive-backup +Local add-ons: + maintainer: you + slug: local + source: local +MickMake Hass.io Add-ons: + maintainer: MickMake + slug: ba22da74 + source: https://github.com/MickMake/HomeAssistantAddons +Official add-ons: + maintainer: Home Assistant + slug: core + source: core +Poeschl Home Assistant Add-ons: + maintainer: Poeschl + slug: 243ffc37 + source: https://github.com/Poeschl/Hassio-Addons +Sanderdw's add-on repository: + maintainer: Sander de Wildt + slug: 0826754b + source: https://github.com/sanderdw/hassio-addons +Tom's Home Assistant Add-ons: + maintainer: Thomas Mauerer + slug: 15d21743 + source: https://github.com/thomasmauerer/hassio-addons +bjeanes Home Assistant add-on repository: + maintainer: Bo Jeanes + slug: 9c51689a + source: https://github.com/bjeanes/hassio-addons +bjeanes' fork of Poeschl Home Assistant Add-ons: + maintainer: bjeanes + slug: 61c150fb + source: https://github.com/bjeanes/Poeschl-Hassio-Addons diff --git a/config/.HA_VERSION b/config/.HA_VERSION new file mode 100644 index 0000000..c25362f --- /dev/null +++ b/config/.HA_VERSION @@ -0,0 +1 @@ +2022.5.2 \ No newline at end of file diff --git a/config/TODO.md b/config/TODO.md new file mode 100644 index 0000000..f7a2fd2 --- /dev/null +++ b/config/TODO.md @@ -0,0 +1,10 @@ +TODO: + +* [ ] Flash rest of Mijia sensors +* [ ] Move secrets so Git exporter can run +* [x] Test magnet on gate opener to see if it marks it closed +* [ ] Fix gate opener + Seems like the reed sensor is failing or the cable is damaged, so always reports open (holding magnet to it does not report closed :\) +* [ ] Cache volumes using dictionary as per https://community.home-assistant.io/t/remember-volume-levels-of-each-source-for-a-media-player-to-automate-restoring/416749/6?u=bjeanes +* [ ] Restore cache for volumes by using a `sql` sensor to read from DB + (template sensors are not restored since they assume they are always calculated, but since it's mutually recursive it does rely on the running state to be accurate) \ No newline at end of file diff --git a/config/automations.yaml b/config/automations.yaml new file mode 100644 index 0000000..2495669 --- /dev/null +++ b/config/automations.yaml @@ -0,0 +1,59 @@ +- id: "1644482494645" + alias: Disable vacuum camera update when docked + description: "" + use_blueprint: + path: PiotrMachowski/disable_vacuum_camera_update_when_docked.yaml + input: + vacuum: vacuum.robot_vacuum + camera: camera.vacuum_map +- id: "1644482497979" + alias: Disable vacuum camera update when docked + description: "" + use_blueprint: + path: PiotrMachowski/disable_vacuum_camera_update_when_docked.yaml + input: + vacuum: vacuum.robot_vacuum + camera: camera.vacuum_map + mode: single +- id: "1650353887007" + alias: Ri's Office Lights + description: "" + use_blueprint: + path: EPMatt/ikea_e1524_e1810.yaml + input: + integration: Zigbee2MQTT + controller_entity: sensor.ikea_remote_action + helper_last_controller_event: input_text.ris_office_ikea_remote_last_action + action_button_center_short: + - service: light.toggle + data: {} + target: + area_id: ri_s_office + action_button_up_short: + - device_id: 27cd6e935587684f83d903e5608ea35c + domain: light + entity_id: light.ris_office + type: brightness_increase + button_up_long_loop: true + button_down_long_loop: true + action_button_up_long: [] + action_button_down_short: + - device_id: 27cd6e935587684f83d903e5608ea35c + domain: light + entity_id: light.ris_office + type: brightness_decrease + action_button_down_long: [] +- id: "1650766227595" + alias: Update OpenUV every 30 minutes during the daytime + trigger: + platform: time_pattern + minutes: /30 + condition: + condition: and + conditions: + - condition: sun + after: sunrise + - condition: sun + before: sunset + action: + service: openuv.update_data diff --git a/config/blueprints/automation/EPMatt/ikea_e1524_e1810.yaml b/config/blueprints/automation/EPMatt/ikea_e1524_e1810.yaml new file mode 100644 index 0000000..9a6a15d --- /dev/null +++ b/config/blueprints/automation/EPMatt/ikea_e1524_e1810.yaml @@ -0,0 +1,811 @@ +blueprint: + name: Controller - IKEA E1524/E1810 TRÅDFRI Wireless 5-Button Remote + description: '# Controller - IKEA E1524/E1810 TRÅDFRI Wireless 5-Button Remote + + + Controller automation for executing any kind of action triggered by the provided + IKEA E1524/E1810 TRÅDFRI Wireless 5-Button Remote. Allows to optionally loop an + action on a button long press. + + Supports deCONZ, ZHA, Zigbee2MQTT. + + + Automations created with this blueprint can be connected with one or more [Hooks](https://epmatt.github.io/awesome-ha-blueprints/docs/blueprints/hooks) + supported by this controller. + + Hooks allow to easily create controller-based automations for interacting with + media players, lights, covers and more. + + See the list of [Hooks available for this controller](https://epmatt.github.io/awesome-ha-blueprints/docs/blueprints/controllers/ikea_e1524_e1810#available-hooks) + for additional details. + + + 📕 Full documentation regarding this blueprint is available [here](https://epmatt.github.io/awesome-ha-blueprints/docs/blueprints/controllers/ikea_e1524_e1810). + + + 🚀 This blueprint is part of the **[Awesome HA Blueprints](https://epmatt.github.io/awesome-ha-blueprints) + project**. + + + ℹ️ Version 2021.10.26 + + ' + source_url: https://github.com/EPMatt/awesome-ha-blueprints/blob/main/blueprints/controllers/ikea_e1524_e1810/ikea_e1524_e1810.yaml + domain: automation + input: + integration: + name: (Required) Integration + description: Integration used for connecting the remote with Home Assistant. + Select one of the available values. + selector: + select: + options: + - deCONZ + - ZHA + - Zigbee2MQTT + custom_value: false + multiple: false + controller_device: + name: (deCONZ, ZHA) Controller Device + description: The controller device to use for the automation. Choose a value + only if the remote is integrated with deCONZ, ZHA. + default: '' + selector: + device: {} + controller_entity: + name: (Zigbee2MQTT) Controller Entity + description: The action sensor of the controller to use for the automation. + Choose a value only if the remote is integrated with Zigbee2MQTT. + default: '' + selector: + entity: + domain: sensor + multiple: false + helper_last_controller_event: + name: (Required) Helper - Last Controller Event + description: Input Text used to store the last event fired by the controller. + You will need to manually create a text input entity for this, please read + the blueprint Additional Notes for more info. + default: '' + selector: + entity: + domain: input_text + multiple: false + action_button_left_short: + name: (Optional) Left button short press + description: Action to run on short left button press. + default: [] + selector: + action: {} + action_button_left_long: + name: (Optional) Left button long press + description: Action to run on long left button press. + default: [] + selector: + action: {} + action_button_left_release: + name: (Optional) Left button release + description: Action to run on left button release after long press. + default: [] + selector: + action: {} + action_button_left_double: + name: (Optional) Left button double press + description: Action to run on double left button press. + default: [] + selector: + action: {} + action_button_right_short: + name: (Optional) Right button short press + description: Action to run on short right button press. + default: [] + selector: + action: {} + action_button_right_long: + name: (Optional) Right button long press + description: Action to run on long right button press. + default: [] + selector: + action: {} + action_button_right_release: + name: (Optional) Right button release + description: Action to run on right button release after long press. + default: [] + selector: + action: {} + action_button_right_double: + name: (Optional) Right button double press + description: Action to run on double right button press. + default: [] + selector: + action: {} + action_button_up_short: + name: (Optional) Up button short press + description: Action to run on short up button press. + default: [] + selector: + action: {} + action_button_up_long: + name: (Optional) Up button long press + description: Action to run on long up button press. + default: [] + selector: + action: {} + action_button_up_release: + name: (Optional) Up button release + description: Action to run on up button release after long press. + default: [] + selector: + action: {} + action_button_up_double: + name: (Optional) Up button double press + description: Action to run on double up button press. + default: [] + selector: + action: {} + action_button_down_short: + name: (Optional) Down button short press + description: Action to run on short down button press. + default: [] + selector: + action: {} + action_button_down_long: + name: (Optional) Down button long press + description: Action to run on long down button press. + default: [] + selector: + action: {} + action_button_down_release: + name: (Optional) Down button release + description: Action to run on down button release after long press. + default: [] + selector: + action: {} + action_button_down_double: + name: (Optional) Down button double press + description: Action to run on double down button press. + default: [] + selector: + action: {} + action_button_center_short: + name: (Optional) Center button short press + description: Action to run on short center button press. + default: [] + selector: + action: {} + action_button_center_long: + name: (Optional) Center button long press + description: Action to run on long center button press. + default: [] + selector: + action: {} + action_button_center_double: + name: (Optional) Center button double press + description: Action to run on double center button press. + default: [] + selector: + action: {} + button_left_long_loop: + name: (Optional) Left button long press - loop until release + description: Loop the left button action until the button is released. + default: false + selector: + boolean: {} + button_left_long_max_loop_repeats: + name: (Optional) Left button long press - Maximum loop repeats + description: Maximum number of repeats for the custom action, when looping is + enabled. Use it as a safety limit to prevent an endless loop in case the corresponding + stop event is not received. + default: 500 + selector: + number: + min: 1.0 + max: 5000.0 + mode: slider + step: 1.0 + button_right_long_loop: + name: (Optional) Right button long press - loop until release + description: Loop the right button action until the button is released. + default: false + selector: + boolean: {} + button_right_long_max_loop_repeats: + name: (Optional) Right button long press - Maximum loop repeats + description: Maximum number of repeats for the custom action, when looping is + enabled. Use it as a safety limit to prevent an endless loop in case the corresponding + stop event is not received. + default: 500 + selector: + number: + min: 1.0 + max: 5000.0 + mode: slider + step: 1.0 + button_up_long_loop: + name: (Optional) Up button long press - loop until release + description: Loop the up button action until the button is released. + default: false + selector: + boolean: {} + button_up_long_max_loop_repeats: + name: (Optional) Up button long press - Maximum loop repeats + description: Maximum number of repeats for the custom action, when looping is + enabled. Use it as a safety limit to prevent an endless loop in case the corresponding + stop event is not received. + default: 500 + selector: + number: + min: 1.0 + max: 5000.0 + mode: slider + step: 1.0 + button_down_long_loop: + name: (Optional) Down button long press - loop until release + description: Loop the down button action until the button is released. + default: false + selector: + boolean: {} + button_down_long_max_loop_repeats: + name: (Optional) Down button long press - Maximum loop repeats + description: Maximum number of repeats for the custom action, when looping is + enabled. Use it as a safety limit to prevent an endless loop in case the corresponding + stop event is not received. + default: 500 + selector: + number: + min: 1.0 + max: 5000.0 + mode: slider + step: 1.0 + button_left_double_press: + name: (Optional) Expose left button double press event + description: Choose whether or not to expose the virtual double press event + for the left button. Turn this on if you are providing an action for the left + button double press event. + default: false + selector: + boolean: {} + button_right_double_press: + name: (Optional) Expose right button double press event + description: Choose whether or not to expose the virtual double press event + for the right button. Turn this on if you are providing an action for the + right button double press event. + default: false + selector: + boolean: {} + button_up_double_press: + name: (Optional) Expose up button double press event + description: Choose whether or not to expose the virtual double press event + for the up button. Turn this on if you are providing an action for the up + button double press event. + default: false + selector: + boolean: {} + button_down_double_press: + name: (Optional) Expose down button double press event + description: Choose whether or not to expose the virtual double press event + for the down button. Turn this on if you are providing an action for the down + button double press event. + default: false + selector: + boolean: {} + button_center_double_press: + name: (Optional) Expose center button double press event + description: Choose whether or not to expose the virtual double press event + for the center button. Turn this on if you are providing an action for the + center button double press event. + default: false + selector: + boolean: {} + helper_double_press_delay: + name: (Optional) Helper - Double Press delay + description: Max delay between the first and the second button press for the + double press event. Provide a value only if you are using a double press action. + Increase this value if you notice that the double press action is not triggered + properly. + default: 500 + selector: + number: + min: 100.0 + max: 5000.0 + unit_of_measurement: milliseconds + mode: box + step: 10.0 + helper_debounce_delay: + name: (Optional) Helper - Debounce delay + description: Delay used for debouncing RAW controller events, by default set + to 0. A value of 0 disables the debouncing feature. Increase this value if + you notice custom actions or linked Hooks running multiple times when interacting + with the device. When the controller needs to be debounced, usually a value + of 100 is enough to remove all duplicate events. + default: 0 + selector: + number: + min: 0.0 + max: 1000.0 + unit_of_measurement: milliseconds + mode: box + step: 10.0 +variables: + integration: !input 'integration' + button_left_long_loop: !input 'button_left_long_loop' + button_left_long_max_loop_repeats: !input 'button_left_long_max_loop_repeats' + button_left_double_press: !input 'button_left_double_press' + button_right_long_loop: !input 'button_right_long_loop' + button_right_long_max_loop_repeats: !input 'button_right_long_max_loop_repeats' + button_right_double_press: !input 'button_right_double_press' + button_up_long_loop: !input 'button_up_long_loop' + button_up_long_max_loop_repeats: !input 'button_up_long_max_loop_repeats' + button_up_double_press: !input 'button_up_double_press' + button_down_long_loop: !input 'button_down_long_loop' + button_down_long_max_loop_repeats: !input 'button_down_long_max_loop_repeats' + button_down_double_press: !input 'button_down_double_press' + button_center_double_press: !input 'button_center_double_press' + helper_last_controller_event: !input 'helper_last_controller_event' + helper_double_press_delay: !input 'helper_double_press_delay' + helper_debounce_delay: !input 'helper_debounce_delay' + integration_id: '{{ integration | lower }}' + adjusted_double_press_delay: '{{ [helper_double_press_delay - helper_debounce_delay, + 100] | max }}' + actions_mapping: + deconz: + button_left_short: + - '4002' + button_left_long: + - '4001' + button_left_release: + - '4003' + button_right_short: + - '5002' + button_right_long: + - '5001' + button_right_release: + - '5003' + button_up_short: + - '2002' + button_up_long: + - '2001' + button_up_release: + - '2003' + button_down_short: + - '3002' + button_down_long: + - '3001' + button_down_release: + - '3003' + button_center_short: + - '1002' + button_center_long: + - '1001' + zha: + button_left_short: + - press_257_13_0 + button_left_long: + - hold_3329_0 + button_left_release: + - release + button_right_short: + - press_256_13_0 + button_right_long: + - hold_3328_0 + button_right_release: + - release + button_up_short: + - step_with_on_off_0_43_5 + button_up_long: + - move_with_on_off_0_83 + - move_with_on_off_0_84 + button_up_release: + - stop + button_down_short: + - step_1_43_5 + button_down_long: + - move_1_83 + - move_1_84 + button_down_release: + - stop + button_center_short: + - toggle + button_center_long: + - press_2_0_0 + zigbee2mqtt: + button_left_short: + - arrow_left_click + button_left_long: + - arrow_left_hold + button_left_release: + - arrow_left_release + button_right_short: + - arrow_right_click + button_right_long: + - arrow_right_hold + button_right_release: + - arrow_right_release + button_up_short: + - brightness_up_click + button_up_long: + - brightness_up_hold + button_up_release: + - brightness_up_release + button_down_short: + - brightness_down_click + button_down_long: + - brightness_down_hold + button_down_release: + - brightness_down_release + button_center_short: + - toggle + button_center_long: + - toggle_hold + button_left_short: '{{ actions_mapping[integration_id]["button_left_short"] }}' + button_left_long: '{{ actions_mapping[integration_id]["button_left_long"] }}' + button_left_release: '{{ actions_mapping[integration_id]["button_left_release"] + }}' + button_right_short: '{{ actions_mapping[integration_id]["button_right_short"] }}' + button_right_long: '{{ actions_mapping[integration_id]["button_right_long"] }}' + button_right_release: '{{ actions_mapping[integration_id]["button_right_release"] + }}' + button_up_short: '{{ actions_mapping[integration_id]["button_up_short"] }}' + button_up_long: '{{ actions_mapping[integration_id]["button_up_long"] }}' + button_up_release: '{{ actions_mapping[integration_id]["button_up_release"] }}' + button_down_short: '{{ actions_mapping[integration_id]["button_down_short"] }}' + button_down_long: '{{ actions_mapping[integration_id]["button_down_long"] }}' + button_down_release: '{{ actions_mapping[integration_id]["button_down_release"] + }}' + button_center_short: '{{ actions_mapping[integration_id]["button_center_short"] + }}' + button_center_long: '{{ actions_mapping[integration_id]["button_center_long"] }}' + integrations_with_prev_event_storage: + - zha + controller_entity: !input 'controller_entity' + controller_device: !input 'controller_device' + controller_id: '{% if integration_id=="zigbee2mqtt" %}{{controller_entity}}{% else + %}{{controller_device}}{% endif %}' +mode: restart +max_exceeded: silent +trigger: +- platform: event + event_type: state_changed + event_data: + entity_id: !input 'controller_entity' +- platform: event + event_type: + - deconz_event + - zha_event + event_data: + device_id: !input 'controller_device' +condition: +- condition: and + conditions: + - '{%- set trigger_action -%} {%- if integration_id == "zigbee2mqtt" -%} {{ trigger.event.data.new_state.state + }} {%- elif integration_id == "deconz" -%} {{ trigger.event.data.event }} {%- + elif integration_id == "zha" -%} {{ trigger.event.data.command }}{{"_" if trigger.event.data.args|length + > 0}}{{ trigger.event.data.args|join("_") }} {%- endif -%} {%- endset -%} {{ trigger_action + not in ["","None"] }}' + - '{{ integration_id != "zigbee2mqtt" or trigger.event.data.new_state.state != trigger.event.data.old_state.state + }}' +action: +- delay: + milliseconds: !input 'helper_debounce_delay' +- variables: + trigger_action: '{%- if integration_id == "zigbee2mqtt" -%} {{ trigger.event.data.new_state.state + }} {%- elif integration_id == "deconz" -%} {{ trigger.event.data.event }} {%- + elif integration_id == "zha" -%} {{ trigger.event.data.command }}{{"_" if trigger.event.data.args|length + > 0}}{{ trigger.event.data.args|join("_") }} {%- endif -%}' + trigger_delta: '{{ (as_timestamp(now()) - as_timestamp((states(helper_last_controller_event) + | from_json).last_triggered if helper_last_controller_event is not none and + (states(helper_last_controller_event) | regex_match("^\{(\".*\": \".*\"(, )?)*\}$")) + else "1970-01-01 00:00:00")) * 1000 }}' + last_controller_event: '{{ (states(helper_last_controller_event) | from_json).trigger_action + if helper_last_controller_event is not none and (states(helper_last_controller_event) + | regex_match("^\{(\".*\": \".*\"(, )?)*\}$")) else "" }}' +- service: input_text.set_value + data: + entity_id: !input 'helper_last_controller_event' + value: '{{ {"trigger_action":trigger_action,"last_triggered":now()|string} | to_json + }}' +- choose: + - conditions: '{{ trigger_action | string in button_left_short }}' + sequence: + - choose: + - conditions: '{{ button_left_double_press }}' + sequence: + - choose: + - conditions: '{{ trigger_action | string in states(helper_last_controller_event) + and trigger_delta | int <= helper_double_press_delay | int }}' + sequence: + - service: input_text.set_value + data: + entity_id: !input 'helper_last_controller_event' + value: '{{ {"trigger_action":"double_press","last_triggered":now() + | string} | to_json }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_left_double + - choose: + - conditions: [] + sequence: !input 'action_button_left_double' + default: + - delay: + milliseconds: '{{ adjusted_double_press_delay }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_left_short + - choose: + - conditions: [] + sequence: !input 'action_button_left_short' + default: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_left_short + - choose: + - conditions: [] + sequence: !input 'action_button_left_short' + - conditions: '{{ trigger_action | string in button_left_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_left_long + - choose: + - conditions: '{{ button_left_long_loop }}' + sequence: + - repeat: + while: '{{ repeat.index < button_left_long_max_loop_repeats | int }}' + sequence: !input 'action_button_left_long' + default: !input 'action_button_left_long' + - conditions: + - '{{ trigger_action | string in button_left_release }}' + - '{{ not integration_id in integrations_with_prev_event_storage or last_controller_event + | string in button_left_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_left_release + - choose: + - conditions: [] + sequence: !input 'action_button_left_release' + - conditions: '{{ trigger_action | string in button_right_short }}' + sequence: + - choose: + - conditions: '{{ button_right_double_press }}' + sequence: + - choose: + - conditions: '{{ trigger_action | string in states(helper_last_controller_event) + and trigger_delta | int <= helper_double_press_delay | int }}' + sequence: + - service: input_text.set_value + data: + entity_id: !input 'helper_last_controller_event' + value: '{{ {"trigger_action":"double_press","last_triggered":now() + | string} | to_json }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_right_double + - choose: + - conditions: [] + sequence: !input 'action_button_right_double' + default: + - delay: + milliseconds: '{{ adjusted_double_press_delay }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_right_short + - choose: + - conditions: [] + sequence: !input 'action_button_right_short' + default: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_right_short + - choose: + - conditions: [] + sequence: !input 'action_button_right_short' + - conditions: '{{ trigger_action | string in button_right_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_right_long + - choose: + - conditions: '{{ button_right_long_loop }}' + sequence: + - repeat: + while: '{{ repeat.index < button_right_long_max_loop_repeats | int }}' + sequence: !input 'action_button_right_long' + default: !input 'action_button_right_long' + - conditions: + - '{{ trigger_action | string in button_right_release }}' + - '{{ not integration_id in integrations_with_prev_event_storage or last_controller_event + | string in button_right_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_right_release + - choose: + - conditions: [] + sequence: !input 'action_button_right_release' + - conditions: '{{ trigger_action | string in button_up_short }}' + sequence: + - choose: + - conditions: '{{ button_up_double_press }}' + sequence: + - choose: + - conditions: '{{ trigger_action | string in states(helper_last_controller_event) + and trigger_delta | int <= helper_double_press_delay | int }}' + sequence: + - service: input_text.set_value + data: + entity_id: !input 'helper_last_controller_event' + value: '{{ {"trigger_action":"double_press","last_triggered":now() + | string} | to_json }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_up_double + - choose: + - conditions: [] + sequence: !input 'action_button_up_double' + default: + - delay: + milliseconds: '{{ adjusted_double_press_delay }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_up_short + - choose: + - conditions: [] + sequence: !input 'action_button_up_short' + default: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_up_short + - choose: + - conditions: [] + sequence: !input 'action_button_up_short' + - conditions: '{{ trigger_action | string in button_up_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_up_long + - choose: + - conditions: '{{ button_up_long_loop }}' + sequence: + - repeat: + while: '{{ repeat.index < button_up_long_max_loop_repeats | int }}' + sequence: !input 'action_button_up_long' + default: !input 'action_button_up_long' + - conditions: + - '{{ trigger_action | string in button_up_release }}' + - '{{ not integration_id in integrations_with_prev_event_storage or last_controller_event + | string in button_up_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_up_release + - choose: + - conditions: [] + sequence: !input 'action_button_up_release' + - conditions: '{{ trigger_action | string in button_down_short }}' + sequence: + - choose: + - conditions: '{{ button_down_double_press }}' + sequence: + - choose: + - conditions: '{{ trigger_action | string in states(helper_last_controller_event) + and trigger_delta | int <= helper_double_press_delay | int }}' + sequence: + - service: input_text.set_value + data: + entity_id: !input 'helper_last_controller_event' + value: '{{ {"trigger_action":"double_press","last_triggered":now() + | string} | to_json }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_down_double + - choose: + - conditions: [] + sequence: !input 'action_button_down_double' + default: + - delay: + milliseconds: '{{ adjusted_double_press_delay }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_down_short + - choose: + - conditions: [] + sequence: !input 'action_button_down_short' + default: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_down_short + - choose: + - conditions: [] + sequence: !input 'action_button_down_short' + - conditions: '{{ trigger_action | string in button_down_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_down_long + - choose: + - conditions: '{{ button_down_long_loop }}' + sequence: + - repeat: + while: '{{ repeat.index < button_down_long_max_loop_repeats | int }}' + sequence: !input 'action_button_down_long' + default: !input 'action_button_down_long' + - conditions: + - '{{ trigger_action | string in button_down_release }}' + - '{{ not integration_id in integrations_with_prev_event_storage or last_controller_event + | string in button_down_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_down_release + - choose: + - conditions: [] + sequence: !input 'action_button_down_release' + - conditions: '{{ trigger_action | string in button_center_short }}' + sequence: + - choose: + - conditions: '{{ button_center_double_press }}' + sequence: + - choose: + - conditions: '{{ trigger_action | string in states(helper_last_controller_event) + and trigger_delta | int <= helper_double_press_delay | int }}' + sequence: + - service: input_text.set_value + data: + entity_id: !input 'helper_last_controller_event' + value: '{{ {"trigger_action":"double_press","last_triggered":now() + | string} | to_json }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_center_double + - choose: + - conditions: [] + sequence: !input 'action_button_center_double' + default: + - delay: + milliseconds: '{{ adjusted_double_press_delay }}' + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_center_short + - choose: + - conditions: [] + sequence: !input 'action_button_center_short' + default: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_center_short + - choose: + - conditions: [] + sequence: !input 'action_button_center_short' + - conditions: '{{ trigger_action | string in button_center_long }}' + sequence: + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_center_long + - choose: + - conditions: [] + sequence: !input 'action_button_center_long' diff --git a/config/blueprints/automation/PiotrMachowski/disable_vacuum_camera_update_when_docked.yaml b/config/blueprints/automation/PiotrMachowski/disable_vacuum_camera_update_when_docked.yaml new file mode 100644 index 0000000..1ad92a6 --- /dev/null +++ b/config/blueprints/automation/PiotrMachowski/disable_vacuum_camera_update_when_docked.yaml @@ -0,0 +1,52 @@ +blueprint: + name: Disable vacuum camera update when docked + description: Disable the automatic update of the vacuum camera when the robot is + docked. + domain: automation + source_url: https://github.com/PiotrMachowski/Home-Assistant-custom-components-Xiaomi-Cloud-Map-Extractor/blob/master/blueprints/automation/disable_vacuum_camera_update_when_docked.yaml + input: + vacuum: + name: Vacuum device + selector: + entity: + domain: vacuum + camera: + name: Vacuum camera + selector: + entity: + domain: camera +mode: restart +trigger: +- platform: state + entity_id: !input 'vacuum' + for: + minutes: 1 + to: 'docked' +- platform: state + entity_id: !input 'vacuum' + for: + minutes: 1 + to: 'unavailable' +- platform: state + entity_id: !input 'vacuum' + for: + minutes: 1 + to: 'unknown' +- platform: state + entity_id: !input 'vacuum' + from: 'docked' +- platform: state + entity_id: !input 'vacuum' + from: 'unavailable' +- platform: state + entity_id: !input 'vacuum' + from: 'unknown' +condition: +- condition: template + value_template: '{{ trigger.to_state.state != trigger.from_state.state }}' +action: +- condition: trigger + id: 0 +- service: "{% if trigger.to_state.state in [\"unavailable\", \"unknown\", \"docked\"\ + ] %}\n camera.turn_off\n{% else %}\n camera.turn_on\n{% endif %}\n" + entity_id: !input 'camera' diff --git a/config/blueprints/automation/homeassistant/motion_light.yaml b/config/blueprints/automation/homeassistant/motion_light.yaml new file mode 100644 index 0000000..c11d22d --- /dev/null +++ b/config/blueprints/automation/homeassistant/motion_light.yaml @@ -0,0 +1,50 @@ +blueprint: + name: Motion-activated Light + description: Turn on a light when motion is detected. + domain: automation + source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/automation/blueprints/motion_light.yaml + input: + motion_entity: + name: Motion Sensor + selector: + entity: + domain: binary_sensor + device_class: motion + light_target: + name: Light + selector: + target: + entity: + domain: light + no_motion_wait: + name: Wait time + description: Time to leave the light on after last motion is detected. + default: 120 + selector: + number: + min: 0 + max: 3600 + unit_of_measurement: seconds + +# If motion is detected within the delay, +# we restart the script. +mode: restart +max_exceeded: silent + +trigger: + platform: state + entity_id: !input motion_entity + from: "off" + to: "on" + +action: + - service: light.turn_on + target: !input light_target + - wait_for_trigger: + platform: state + entity_id: !input motion_entity + from: "on" + to: "off" + - delay: !input no_motion_wait + - service: light.turn_off + target: !input light_target diff --git a/config/blueprints/script/homeassistant/confirmable_notification.yaml b/config/blueprints/script/homeassistant/confirmable_notification.yaml new file mode 100644 index 0000000..d52e5a6 --- /dev/null +++ b/config/blueprints/script/homeassistant/confirmable_notification.yaml @@ -0,0 +1,84 @@ +blueprint: + name: Confirmable Notification + description: >- + A script that sends an actionable notification with a confirmation before + running the specified action. + domain: script + source_url: https://github.com/home-assistant/core/blob/master/homeassistant/components/script/blueprints/confirmable_notification.yaml + input: + notify_device: + name: Device to notify + description: Device needs to run the official Home Assistant app to receive notifications. + selector: + device: + integration: mobile_app + title: + name: "Title" + description: "The title of the button shown in the notification." + default: "" + selector: + text: + message: + name: "Message" + description: "The message body" + selector: + text: + confirm_text: + name: "Confirmation Text" + description: "Text to show on the confirmation button" + default: "Confirm" + selector: + text: + confirm_action: + name: "Confirmation Action" + description: "Action to run when notification is confirmed" + default: [] + selector: + action: + dismiss_text: + name: "Dismiss Text" + description: "Text to show on the dismiss button" + default: "Dismiss" + selector: + text: + dismiss_action: + name: "Dismiss Action" + description: "Action to run when notification is dismissed" + default: [] + selector: + action: + +mode: restart + +sequence: + - alias: "Set up variables" + variables: + action_confirm: "{{ 'CONFIRM_' ~ context.id }}" + action_dismiss: "{{ 'DISMISS_' ~ context.id }}" + - alias: "Send notification" + domain: mobile_app + type: notify + device_id: !input notify_device + title: !input title + message: !input message + data: + actions: + - action: "{{ action_confirm }}" + title: !input confirm_text + - action: "{{ action_dismiss }}" + title: !input dismiss_text + - alias: "Awaiting response" + wait_for_trigger: + - platform: event + event_type: mobile_app_notification_action + event_data: + action: "{{ action_confirm }}" + - platform: event + event_type: mobile_app_notification_action + event_data: + action: "{{ action_dismiss }}" + - choose: + - conditions: "{{ wait.trigger.event.data.action == action_confirm }}" + sequence: !input confirm_action + - conditions: "{{ wait.trigger.event.data.action == action_dismiss }}" + sequence: !input dismiss_action diff --git a/config/configuration.yaml b/config/configuration.yaml new file mode 100644 index 0000000..c5a6a6a --- /dev/null +++ b/config/configuration.yaml @@ -0,0 +1,53 @@ +# vim:set ts=2 sw=2 tw=0 et: + +# Configure a default setup of Home Assistant (frontend, api, etc) +default_config: + +homeassistant: + packages: !include_dir_named packages + customize: !include customize.yaml + customize_glob: + "sensor.*_fire_danger*": + icon: "mdi:fire" + "switch.*plug*": + icon: "mdi:power-socket-au" + allowlist_external_dirs: + - /config + +recorder: + db_url: !secret recorder_db + commit_interval: 30 + +http: + use_x_forwarded_for: true + trusted_proxies: + - !secret lan_subnet + - !secret iot_subnet + - !secret not_subnet + +frontend: + themes: !include_dir_merge_named themes + +logger: + default: warning + logs: + homeassistant.loader: error + +ffmpeg: + +# Text to speech +tts: + - platform: google_translate + +automation: !include automations.yaml +script: !include scripts.yaml +scene: !include scenes.yaml + +spotify: + client_id: !secret spotify_client_id + client_secret: !secret spotify_client_secret + +google: + client_id: !secret google_client_id + client_secret: !secret google_client_secret + track_new_calendar: false diff --git a/config/customize.yaml b/config/customize.yaml new file mode 100644 index 0000000..7088ff9 --- /dev/null +++ b/config/customize.yaml @@ -0,0 +1,8 @@ +sensor.rtorrent_all_torrents: + unit_of_measurement: torrents +sensor.rtorrent_active_torrents: + unit_of_measurement: torrents +sensor.rtorrent_downloading_torrents: + unit_of_measurement: torrents +sensor.rtorrent_uploading_torrents: + unit_of_measurement: torrents diff --git a/config/groups.yaml b/config/groups.yaml new file mode 100644 index 0000000..e69de29 diff --git a/config/packages/3d_printing.yaml b/config/packages/3d_printing.yaml new file mode 100644 index 0000000..73bbfa3 --- /dev/null +++ b/config/packages/3d_printing.yaml @@ -0,0 +1,54 @@ +switch: + - platform: command_line + switches: + 3d_printer_connection: + # 3d_printer_command_on: /usr/bin/curl -m 10 -d '{"command":"connect"}' -H 'Content-Type: application/json' -H 'X-Api-Key: REDACTED' http://REDACTED/api/connection + command_on: !secret 3d_printer_command_on + + # 3d_printer_command_off: /usr/bin/curl -m 10 -d '{"command":"disconnect"}' -H 'Content-Type: application/json' -H 'X-Api-Key: REDACTED' http://REDACTED/api/connection + command_off: !secret 3d_printer_command_off + + # 3d_printer_command_state: /usr/bin/curl -m 3 -H 'X-Api-Key: REDACTED' http://REDACTED/api/connection + command_state: !secret 3d_printer_command_state + value_template: > + {{ value_json is defined + and value_json.current != None + and value_json.current.state != "Closed" + }} + friendly_name: 3D Printer Connection + unique_id: F36FEDD3D5A14044B4BA7DC01A22CB6A + icon_template: > + {% if is_state('switch.3d_printer_connection', 'on') %} + mdi:lan-connect + {% else %} + mdi:lan-disconnect + {% endif %} + +automation: + - id: "1648468335659" + alias: Turn off 3D printer when inactive + description: "" + trigger: + - platform: state + entity_id: sensor.octoprint_current_state + to: Operational + for: + hours: 0 + minutes: 20 + seconds: 0 + from: Printing + - platform: state + entity_id: sensor.octoprint_current_state + from: unavailable + to: Operational + for: + hours: 1 + minutes: 0 + seconds: 0 + condition: [] + action: + - type: turn_off + device_id: 88f6e49883695cfe34b990b70512421a + entity_id: switch.3d_printer_plug + domain: switch + mode: single diff --git a/config/packages/ble_gateway.yaml b/config/packages/ble_gateway.yaml new file mode 100644 index 0000000..ceacf6b --- /dev/null +++ b/config/packages/ble_gateway.yaml @@ -0,0 +1,63 @@ +input_boolean: + settings_ble_gateway: + name: BLE Gateway + icon: mdi:bluetooth + +input_text: + settings_ble_gateway_add_device: + name: BLE Gateway Add Device + icon: mdi:bluetooth-connect + initial: "" + +template: + - binary_sensor: + - name: BLE Gateway + icon: mdi:bluetooth + state: "{{ is_state('input_boolean.settings_ble_gateway', 'on') }}" + attributes: + devices: >- + {{ states + | selectattr('attributes.mac_address', 'defined') + | rejectattr('attributes.IP', 'defined') + | rejectattr('attributes.ip', 'defined') + | rejectattr('attributes.lan_ip', 'defined') + | map(attribute='attributes.mac_address') + | unique + | sort + | join('') + | replace(':', '') + ~ (states('input_text.settings_ble_gateway_add_device') + | replace(':', '') + | replace(' ', '') + | trim) if is_state('binary_sensor.ble_gateway', 'on') + }} + + - name: "Bluetooth stalled" + state: >- + {% set last_update = states + | selectattr('attributes.mac_address', 'defined') + | rejectattr('attributes.IP', 'defined') + | rejectattr('attributes.ip', 'defined') + | rejectattr('attributes.lan_ip', 'defined') + | map(attribute='last_updated') + | max %} + {{ (as_timestamp(now())-as_timestamp(last_update)) > 120 }} + device_class: problem + icon: >- + {% if is_state("binary_sensor.bluetooth_stalled", "on") %} + mdi:bluetooth-off + {% else %} + mdi:bluetooth + {% endif %} + +automation: + - id: ble_gateway_advertise + alias: ESPHome BLE Advertise + mode: queued + trigger: + - platform: event + event_type: esphome.on_ble_advertise + action: + - service: ble_monitor.parse_data + data: + packet: "{{ trigger.event.data.packet }}" diff --git a/config/packages/debug.yaml b/config/packages/debug.yaml new file mode 100644 index 0000000..09c8797 --- /dev/null +++ b/config/packages/debug.yaml @@ -0,0 +1,33 @@ +sensor: + - platform: sql + db_url: !secret recorder_db + queries: + - name: Recorder age + column: "last_state_age" + unit_of_measurement: seconds + ## For SQLite + #query: > + # SELECT strftime("%s", "now") - strftime("%s", last_updated) + # AS last_state_age + # , last_updated + # FROM "states" + # ORDER BY last_updated DESC + # LIMIT 1 + + # For Postgres + query: > + SELECT extract(epoch from now() - last_updated) + AS last_state_age + , last_updated + FROM "states" + ORDER BY last_updated DESC + LIMIT 1 + - platform: systemmonitor + resources: + - type: disk_use_percent + arg: /config + - type: memory_use_percent + - type: load_1m + - type: load_5m + - type: load_15m + - type: processor_use diff --git a/config/packages/electricity.yaml b/config/packages/electricity.yaml new file mode 100644 index 0000000..426bfc8 --- /dev/null +++ b/config/packages/electricity.yaml @@ -0,0 +1,8 @@ +template: + - sensor: + - unique_id: current_electricity_cost + state: | + {{ (states('sensor.electricity_general_price') | float * states('sensor.eagle_200_meter_power_demand') | float) | round(2) }} + unit_of_measurement: $/hr + device_class: monetary + name: Current electricity cost diff --git a/config/packages/export.yaml b/config/packages/export.yaml new file mode 100644 index 0000000..fe5c3b9 --- /dev/null +++ b/config/packages/export.yaml @@ -0,0 +1,11 @@ +automation: + - id: f0ca9ef44d3b606864eea88a4704baf60d33614b + alias: Export HA config to git repo + trigger: + - platform: time_pattern + hours: "*" + minutes: 25 + action: + - service: hassio.addon_start + data: + addon: "core_letsencrypt" diff --git a/config/packages/gate.yaml b/config/packages/gate.yaml new file mode 100644 index 0000000..eb81777 --- /dev/null +++ b/config/packages/gate.yaml @@ -0,0 +1,123 @@ +# alert: +# front_gate: +# name: Front gate is open +# message: >- # templatable +# Gate has been left open +# skip_first: true # don't send immediately on true condition (HomeKit already does) +# repeat: [10, 20, 60, 120] +# entity_id: cover.front_gate +# state: open +# notifiers: +# - mobile_app_bos_iphone +# data: +# actions: +# - action: close_gate +# title: Close gate +# push: +# interruption-level: time-sensitive + +automation: + - id: close_front_gate_from_alert + alias: Close front gate from alert + trigger: + - platform: event + event_type: mobile_app_notification_action + event_data: + action: close_gate + condition: >- + {{ is_state('cover.front_gate', 'open')}} + action: + - service: cover.close_cover + target: + entity_id: cover.front_gate + + # - id: restart_gate_if_stuck_in_state + # alias: Restart gate if stuck in state + # trigger: + # - platform: state + # entity_id: cover.front_gate + # to: "opening" + # for: + # minutes: 2 + # - platform: state + # entity_id: cover.front_gate + # to: "closing" + # for: + # minutes: 2 + # action: + # - service: button.press + # target: + # entity_id: button.front_gate_restart + + - id: "1649564112896" + alias: Open Gate When Coming Home + description: "" + trigger: + - platform: numeric_state + entity_id: proximity.bo_home + below: "500" + condition: + - condition: state + entity_id: proximity.bo_home + attribute: dir_of_travel + state: towards + - condition: state + entity_id: sensor.bos_iphone_activity + state: Automotive + - condition: state + entity_id: sensor.bos_iphone_activity + attribute: Confidence + state: High + action: + - service: cover.open_cover + data: {} + target: + entity_id: cover.front_gate +# +# # automation: +# - id: "1636803117218" +# alias: Alert if gate left open +# description: "" +# trigger: +# - platform: state +# for: +# hours: 0 +# minutes: 20 +# seconds: 0 +# entity_id: cover.front_gate +# to: open +# action: +# - alias: Set up variables for the actions +# variables: +# action_close: "{{ 'CLOSE_' ~ context.id }}" +# - service: notify.mobile_app_bos_iphone +# data: +# message: Gate has been open for 20 minutes or more +# title: Gate left open +# data: +# actions: +# - action: "{{ action_close }}" +# title: Close gate +# push: +# interruption-level: time-sensitive +# - alias: Wait for a response +# wait_for_trigger: +# - platform: event +# event_type: mobile_app_notification_action +# event_data: +# action: "{{ action_close }}" +# - alias: Perform the action +# choose: +# - conditions: +# - condition: template +# value_template: "{{ wait.trigger.event.data.action == action_close }}" +# sequence: +# - condition: not +# conditions: +# - condition: state +# entity_id: cover.front_gate +# state: closed +# - service: cover.close_cover +# target: +# entity_id: cover.front_gate +# mode: single diff --git a/config/packages/grow.yaml b/config/packages/grow.yaml new file mode 100644 index 0000000..4fbbda8 --- /dev/null +++ b/config/packages/grow.yaml @@ -0,0 +1,420 @@ +android_ip_webcam: + - host: 10.10.10.112 + name: Tent Cam + sensors: + - battery_level + - battery_temp + - light + - proximity + switches: + - exposure_lock + - ffc + - focus + - night_vision + - overlay + +camera: + - platform: mjpeg_timelapse + image_url: http://10.10.10.112:8080/shot.jpg + name: Tent Timelapse + fetch_interval: 3600 + max_frames: 36 + framerate: 10 + quality: 80 + loop: true + +template: + - binary_sensor: + - unique_id: tent_lights_status + name: Tent lights status + delay_on: "0:00:05" + delay_off: "0:00:05" + state: | + {{ states('sensor.tent_wattage') | float > 150 }} + attributes: + device_class: power + - sensor: + - unique_id: tent_temperature_cached + name: Tent Temperature (cached) + unit_of_measurement: °C + device_class: temperature + state_class: measurement + state: | + {{ float(states('sensor.tent_temperature'), default=states('sensor.tent_temperature_cached')) }} + + - unique_id: tent_humidity_cached + name: Tent Humidity (cached) + unit_of_measurement: "%" + device_class: humidity + state_class: measurement + state: | + {{ float(states('sensor.tent_humidity'), default=states('tent_humidity_cached')) }} + + - unique_id: tent_svp + name: "Tent SVP (Saturation Vapor Pressure)" + unit_of_measurement: kPa + device_class: pressure + state_class: measurement + state: | + {% set T = float(states('sensor.tent_temperature_cached')) %} + {% if is_number(T) %} + {{ (0.61078 * e ** (17.2694 * T / (T + 238.3))) | round(3) }} + {% else %} + {{ states('sensor.tent_svp') | round(3) }} + {% endif %} + - unique_id: tent_avp + name: "Tent AVP (Actual Vapor Pressure)" + unit_of_measurement: kPa + device_class: pressure + state_class: measurement + state: | + {% set SVP = float(states('sensor.tent_svp')) %} + {% set RH = float(states('sensor.tent_humidity_cached')) %} + {% if is_number(SVP) and is_number(RH) %} + {{ (SVP * (RH/100.0)) | round(3) }} + {% else %} + {{ states('sensor.tent_avp') | round(3) }} + {% endif %} + - unique_id: tent_vpd + name: "Tent VPD (Vapor Pressure Deficit)" + unit_of_measurement: kPa + device_class: pressure + state_class: measurement + state: | + {% set SVP = float(states('sensor.tent_svp')) %} + {% set AVP = float(states('sensor.tent_avp')) %} + {% if is_number(SVP) and is_number(AVP) %} + {{ (SVP - AVP) | round(3) }} + {% else %} + {{ states('sensor.tent_vpd') | round(3) }} + {% endif %} + +automation: + - id: "1635395611631" + alias: Tent Cam Night Mode When Light Is Off + description: "" + trigger: + - platform: device + type: turned_off + device_id: 3a26463c21d89cc84ffad181fa45ff06 + entity_id: switch.tent_power_strip_grow_lights + domain: switch + for: + hours: 0 + minutes: 0 + seconds: 5 + milliseconds: 0 + condition: [] + action: + - service: switch.turn_on + target: + entity_id: switch.tent_cam_night_vision + mode: single + - id: "1635395660038" + alias: Tent Cam Night Mode When Light Is On + description: "" + trigger: + - platform: device + type: turned_on + device_id: 3a26463c21d89cc84ffad181fa45ff06 + entity_id: switch.tent_power_strip_grow_lights + domain: switch + for: + hours: 0 + minutes: 0 + seconds: 5 + milliseconds: 0 + condition: [] + action: + - service: switch.turn_off + target: + entity_id: switch.tent_cam_night_vision + mode: single + - id: "1635483973733" + alias: Restore tent power strip's state when available + description: "" + trigger: + - platform: state + entity_id: switch.tent_lights_local + from: unavailable + to: "off" + - platform: state + entity_id: switch.tent_usb_local + from: unavailable + to: "off" + - platform: state + entity_id: switch.tent_fans_local + from: unavailable + to: "off" + - platform: state + entity_id: switch.tent_misc_local + from: unavailable + to: "off" + - platform: state + entity_id: switch.tent_humidifier_local + from: unavailable + to: "off" + condition: [] + action: + - scene: scene.tent_power_strip_state + mode: restart + - id: "1635546763394" + alias: Snapshot Tent Power Strip state on any state change + description: + Allows restoring that state when the device goes offline and comes + back online + trigger: + - platform: state + entity_id: switch.tent_misc_local + - platform: state + entity_id: switch.tent_lights_local + - platform: state + entity_id: switch.tent_fans_local + - platform: state + entity_id: switch.tent_usb_local + - platform: state + entity_id: switch.tent_humidifier_local + condition: [] + action: + - service: scene.create + data: + scene_id: tent_power_strip_state + snapshot_entities: + - switch.tent_lights_local + - switch.tent_fans_local + - switch.tent_humidifier_local + - switch.tent_misc_local + - switch.tent_usb_local + mode: restart + - id: "1635838578022" + alias: Tent lights off + description: "" + trigger: + - platform: time + at: "17:30:00" + condition: [] + action: + - type: turn_off + device_id: 3a26463c21d89cc84ffad181fa45ff06 + entity_id: switch.tent_power_strip_grow_lights + domain: switch + mode: single + - id: "1635838786987" + alias: Tent lights on after 6 hrs + description: "" + trigger: + - platform: time + at: "23:30:00" + condition: [] + action: + - type: turn_on + device_id: 3a26463c21d89cc84ffad181fa45ff06 + entity_id: switch.tent_power_strip_grow_lights + domain: switch + mode: single + - id: "1635838809246" + alias: Tent lights on after 12 hrs + description: "" + trigger: + - platform: time + at: 05:30:00 + condition: [] + action: + - type: turn_on + device_id: 3a26463c21d89cc84ffad181fa45ff06 + entity_id: switch.tent_power_strip_grow_lights + domain: switch + mode: single + - id: "1640915453691" + alias: Alert if pH drops out of range + description: "" + trigger: + - platform: numeric_state + entity_id: sensor.tent_reservoir_ph + above: input_number.maximum_ph + for: + hours: 0 + minutes: 5 + seconds: 0 + - platform: numeric_state + entity_id: sensor.tent_reservoir_ph + below: input_number.minimum_ph + for: + hours: 0 + minutes: 5 + seconds: 0 + condition: [] + action: + - device_id: 180bff5b35717d9bb9082d52551b5065 + domain: mobile_app + type: notify + message: pH outside of specified range + mode: single + - id: "1644557480025" + alias: Turn on tent humidifier + description: if VPD is high _and_ it is not above maximum allowable humidity + trigger: + - platform: numeric_state + entity_id: sensor.tent_vpd + above: input_number.maximum_tent_vpd + for: + hours: 0 + minutes: 0 + seconds: 0 + - platform: numeric_state + entity_id: sensor.tent_humidity_cached + below: input_number.minimum_tent_humidity + condition: + - condition: numeric_state + entity_id: sensor.tent_humidity_cached + below: input_number.maximum_tent_humidity + action: + - service: switch.turn_on + data: {} + target: + entity_id: + - switch.tent_humidifier + - switch.tent_humidifier_local + mode: restart + - id: "1644557631412" + alias: Turn off tent humidifier + description: if VPD in range or humidity too high + trigger: + - platform: numeric_state + entity_id: sensor.tent_vpd + for: + hours: 0 + minutes: 0 + seconds: 0 + below: input_number.minimum_tent_vpd + - platform: numeric_state + entity_id: sensor.tent_humidity_cached + above: input_number.maximum_tent_humidity + for: + hours: 0 + minutes: 0 + seconds: 0 + condition: + - condition: or + conditions: + - condition: numeric_state + entity_id: sensor.tent_wattage + below: "150" + - condition: numeric_state + entity_id: sensor.tent_humidity_cached + above: input_number.minimum_tent_humidity + action: + - service: switch.turn_off + data: {} + target: + entity_id: + - switch.tent_humidifier + - switch.tent_humidifier_local + mode: restart + - id: "1644716285765" + alias: Re-focus tent cam regularly + description: "" + trigger: + - platform: time_pattern + minutes: /5 + seconds: "0" + hours: "*" + condition: + - condition: numeric_state + entity_id: sensor.tent_wattage + above: "150" + action: + - service: switch.toggle + data: {} + target: + entity_id: switch.tent_cam_focus + - delay: + hours: 0 + minutes: 0 + seconds: 3 + milliseconds: 0 + - service: switch.toggle + data: {} + target: + entity_id: switch.tent_cam_focus + mode: single + - id: "1645058611536" + alias: Count humidifier run time + description: "" + trigger: + - platform: time_pattern + seconds: /1 + condition: + - condition: device + type: is_on + device_id: 4f8a04a40876b2a1914ea8d004b6aac5 + entity_id: switch.tent_humidifier_local + domain: switch + action: + - service: counter.increment + data: {} + target: + entity_id: counter.humidifier_run_time_since_refill + mode: queued + max: 120 + - id: "1645060500738" + alias: Humidifier tank timer + description: "" + trigger: + - platform: device + type: turned_on + device_id: 4f8a04a40876b2a1914ea8d004b6aac5 + entity_id: switch.tent_humidifier_local + domain: switch + - platform: device + type: turned_off + device_id: 4f8a04a40876b2a1914ea8d004b6aac5 + entity_id: switch.tent_humidifier_local + domain: switch + condition: [] + action: + - service: + "timer.{{ 'start' if trigger.to_state.state == 'on' else 'pause' + }} + + " + data: {} + target: + entity_id: timer.humidifier_time_till_refill + mode: restart + - id: "1647038709985" + alias: Disable timelapse when lights off + description: "" + trigger: + - platform: numeric_state + entity_id: sensor.tent_wattage + for: + hours: 0 + minutes: 0 + seconds: 30 + below: "100" + condition: [] + action: + - service: mjpeg_timelapse.pause_recording + data: {} + target: + entity_id: camera.tent_timelapse + mode: single + - id: "1647038771614" + alias: Enable timelapse when lights on + description: "" + trigger: + - platform: numeric_state + entity_id: sensor.tent_wattage + for: + hours: 0 + minutes: 15 + seconds: 0 + above: "180" + condition: [] + action: + - service: mjpeg_timelapse.resume_recording + data: {} + target: + entity_id: camera.tent_timelapse + mode: single diff --git a/config/packages/home.yaml b/config/packages/home.yaml new file mode 100644 index 0000000..b365c62 --- /dev/null +++ b/config/packages/home.yaml @@ -0,0 +1,181 @@ +homeassistant: + customize_glob: + "input_boolean.*_in_bed": + templates: # custom-ui + icon: > + if (state === 'on') + return 'mdi:bed'; + return 'mdi:bed-empty'; + +proximity: + bo_home: + zone: home + unit_of_measurement: m + devices: + - person.bo_jeanes + ri_home: + zone: home + unit_of_measurement: m + devices: + - person.ri_liu + +group: + family: + name: Family + entities: + - person.bo_jeanes + - person.ri_liu + anyone_in_bed: + name: Anyone in bed + entities: + - input_boolean.bo_in_bed + - input_boolean.ri_in_bed + everyone_in_bed: + name: Everyone in bed + all: true + entities: + - input_boolean.bo_in_bed + - input_boolean.ri_in_bed + +automation: + - id: not_in_bed + alias: No longer in bed when phone leaves room + trigger: + - platform: state + entity_id: + - sensor.ri_s_phone + from: "bedroom" + variables: + toggle: input_boolean_ri_in_bed + for: + minutes: 1 + - platform: state + entity_id: + - sensor.ri_s_phone + variables: + toggle: input_boolean_bo_in_bed + from: "bedroom" + for: + minutes: 1 + condition: + - "{{ trigger.to_state.state not in ['not_home', 'unknown', 'unavailable'] }}" + - "{{ is_state(toggle, 'on') }}" + action: + - service: input_boolean.turn_off + target: + entity_id: "{{ toggle }}" + - id: in_bed + alias: In bed detection (based on phone charging) + trigger: + - platform: state + entity_id: sensor.ris_iphone_hass_battery_state + variables: + # battery_state can be: Full, Charging, Not Charging. + target_state: '{% if is_state("sensor.ris_iphone_hass_battery_state", "Not Charging") %}off{% else %}on{% endif %}' + toggle: input_boolean.ri_in_bed + person: person.ri_liu + - platform: state + entity_id: sensor.bos_iphone_hass_battery_state + variables: + target_state: '{% if is_state("sensor.bos_iphone_hass_battery_state", "Not Charging") %}off{% else %}on{% endif %}' + toggle: input_boolean.bo_in_bed + person: person.bo_jeanes + condition: + - or: + - "{{ target_state == 'off' }}" + - alias: "plausible sleep time" + condition: time + after: "21:00:00" + before: "10:00:00" + - "{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}" + - "{{ not is_state(toggle, target_state) }}" + - "{{ is_state(person, 'home') }}" + action: + - service: "input_boolean.turn_{{ target_state }}" + data: + entity_id: "{{ toggle }}" + +template: + - binary_sensor: + - unique_id: in_bed + name: In bed + state: | + {{ is_state('input_boolean.bo_in_bed', 'on') or is_state('input_boolean.ri_in_bed', 'on') }} + icon: | + {% if is_state("binary_sensor.in_bed", "on") %} + mdi:bed + {% else %} + mdi:bed-empty + {% endif %} + device_class: occupancy + - unique_id: sleeping + name: Sleeping + state: | + {{ is_state('input_boolean.bo_in_bed', 'on') and is_state('input_boolean.ri_in_bed', 'on') }} + icon: | + {% if is_state("binary_sensor.sleeping", "on") %} + mdi:bed + {% else %} + mdi:bed-empty + {% endif %} + +lifx: + light: + - broadcast: !secret iot_broadcast + +homekit: + - name: house + port: 21223 + filter: + include_entities: + - vacuum.robot_vacuum + # - sensor.bathroom_temperature + # - sensor.bathroom_humidity + # - sensor.bo_s_office_temperature + # - sensor.bo_s_office_humidity + # - sensor.kitchen_temperature + # - sensor.kitchen_humidity + # - sensor.living_room_temperature + # - sensor.living_room_humidity + # - sensor.lounge_room_temperature + # - sensor.lounge_room_humidity + # - sensor.shower_air_temperature + # - sensor.shower_humidity + + - fan.bedroom_purifier + - sensor.bedroom_purifier_humidity + - sensor.bedroom_purifier_pm2_5 + - sensor.bedroom_purifier_temperature + + - input_boolean.bo_in_bed + - input_boolean.ri_in_bed + # - binary_sensor.in_bed + + - switch.bo_s_desk_plug + - switch.bo_s_office_plug + - switch.ri_s_desk_plug + include_entity_globs: + - binary_sensor.*_is_occupied + - sensor.ble_temperature* + - sensor.ble_humidity* + - sensor.ble_illuminance* + include_domains: + - light + exclude_entities: [] + exclude_entity_globs: + - "*.*tent*" + - "sensor.*fridge*" + - "sensor.*freezer*" + - "sensor.*cure*" + - "sensor.*stash*" + - sensor.*garden* + - sensor.*battery_temperature* + - sensor.*forecast* + - sensor.*weather* + - sensor.nas_* + - sensor.*_nas_* + exclude_domains: [] + entity_config: + vacuum.robot_vacuum: + linked_battery_sensor: sensor.robot_vacuum_battery_level + linked_battery_charging_sensor: binary_sensor.robot_vacuum_charging diff --git a/config/packages/media_centre.yaml b/config/packages/media_centre.yaml new file mode 100644 index 0000000..c84645e --- /dev/null +++ b/config/packages/media_centre.yaml @@ -0,0 +1,390 @@ +template: + - trigger: + - platform: time_pattern + seconds: "/10" + sensor: + - unique_id: living_room_media_player_source_volumes + name: Living Room Media Player Source Volumes + state: "voluming" + attributes: + volumes: | + {{ state_attr('sensor.current_living_room_media_player', 'volumes') or [] }} + + - binary_sensor: + - unique_id: should_play_background_music + name: Should play background music + state: | + {{ is_state('group.family', 'home') and is_state('group.anyone_in_bed', 'off') }} + icon: | + {% if is_state('binary_sensor.should_play_background_music', 'on')%} + mdi:music + {% else %} + mdi:music-off' + {% endif %} + + - sensor: + - unique_id: current_living_room_media_player + name: Current Living Room Media Player + state: | + {% if is_state('media_player.apple_tv', 'playing') + or is_state_attr('media_player.denon_avr_x1600h', 'source', 'Media Player') + or is_state_attr('media_player.denon_avr_x1600h', 'source', 'Apple TV') %} + media_player.apple_tv + {% elif is_state_attr('media_player.spotify_bjeanes', 'source', 'Denon AVR-X1600H') or state_attr('media_player.denon_avr_x1600h_heos', 'media_content_id').startswith('spotify:') %} + media_player.spotify_bjeanes + {% elif is_state_attr('media_player.denon_avr_x1600h', 'source', 'HEOS Music') %} + media_player.denon_avr_x1600h_heos + {% else %} + media_player.denon_avr_x1600h + {% endif %} + attributes: + state: > + {{ states(states('sensor.current_living_room_media_player')) }} + source: > + {{ state_attr(states('sensor.current_living_room_media_player'), 'source') }} + device_class: "tv" # so we can expose it to HomeKit with channel controls + volumes: >- + {% set cached_volumes = state_attr('sensor.living_room_media_player_source_volumes', 'volumes') %} + {% if cached_volumes in ["unknown", "unavailable", None, ""] %} + {% set cached_volumes = [] %} + {% endif %} + + {% set volumes = namespace(list= []) %} + {% set sources = [ + state_attr('media_player.denon_avr_x1600h', 'source'), + state_attr('media_player.denon_avr_x1600h_heos', 'source'), + state_attr('sensor.current_living_room_media_player', 'source') + ] | unique | list %} + {% set level = state_attr('media_player.denon_avr_x1600h', 'volume_level') %} + + {# copy over volumes for other sources #} + {% for v in cached_volumes %} + {% if v.source != None and v.source not in sources %} + {% set volumes.list = volumes.list + [v] %} + {% endif %} + {% endfor %} + + {# update volumes for current sources #} + {% for source in sources %} + {% if source != None %} + {% set volumes.list = volumes.list + [{"source": source, "volume_level": level}] %} + {% endif %} + {% endfor %} + + {{ volumes.list }} + + # TODO: pull volume/is_muted from Apple TV (when using AirPods) or from TV (when Denon is off) + is_volume_muted: > + {% if states('media_player.denon_avr_x1600h') in ['idle', 'on', 'playing'] %} + {{ state_attr('media_player.denon_avr_x1600h', 'is_volume_muted') }} + {% else %} + unknown + {% endif %} + volume_level: > + {% if states('media_player.denon_avr_x1600h') in ['idle', 'on', 'playing'] %} + {{ state_attr('media_player.denon_avr_x1600h', 'volume_level') }} + {% else %} + unknown + {% endif %} + icon: > + {% if is_state('sensor.current_living_room_media_player', 'media_player.apple_tv') %} + mdi:apple-tv + {% elif is_state('sensor.current_living_room_media_player', 'media_player.spotify_bjeanes') %} + mdi:spotify + {% elif is_state('sensor.current_living_room_media_player', 'media_player.denon_avr_x1600h_heos') %} + mdi:audio-video + {% elif is_state('sensor.current_living_room_media_player', 'media_player.denon_avr_x1600h') %} + {% if is_state_attr('media_player.denon_avr_x1600h', 'source', 'Tuner') %} + mdi:radio + {% else %} + mdi:audio-video + {% endif %} + {% else %} + mdi:audio-video-off + {% endif %} + + - unique_id: current_living_room_media_player_source + name: Current Living Room Media Player Source + state: | + {%- if is_state('media_player.apple_tv', 'playing') + or is_state_attr('media_player.denon_avr_x1600h', 'source', 'Media Player') + or is_state_attr('media_player.denon_avr_x1600h', 'source', 'Apple TV') -%} + {%- if state_attr('media_player.apple_tv', 'app_name') != None -%} + {{ state_attr('media_player.apple_tv', 'app_name') }} + {%- else -%} + Apple TV + {%- endif -%} + {%- elif is_state_attr('media_player.denon_avr_x1600h', 'source', 'Tuner') %} + Radio + {%- elif is_state_attr('media_player.denon_avr_x1600h', 'source', 'TV') %} + TV + {%- elif not is_state('media_player.spotify_bjeanes', 'idle') + and (is_state_attr('media_player.spotify_bjeanes', 'source', 'Denon AVR-X1600H') or + state_attr('media_player.denon_avr_x1600h_heos', 'media_content_id').startswith('spotify:') + ) -%} + Spotify + {%- elif is_state_attr('media_player.denon_avr_x1600h', 'source', 'HEOS Music') -%} + {{ state_attr('media_player.denon_avr_x1600h_heos', 'source') }} + {%- endif -%} + icon: > + {% if is_state('sensor.current_living_room_media_player_source', 'Apple TV') %} + mdi:apple-tv + {% elif is_state('sensor.current_living_room_media_player_source', 'Radio') %} + mdi:radio + {% elif is_state('sensor.current_living_room_media_player_source', 'Spotify') %} + mdi:spotify + {% elif is_state('sensor.current_living_room_media_player', 'media_player.denon_avr_x1600h_heos') or is_state('sensor.current_living_room_media_player', 'media_player.denon_avr_x1600h') %} + mdi:audio-video + {% else %} + mdi:audio-video-off + {% endif %} + attributes: + source_list: > + {%- set current_source = states('sensor.current_living_room_media_player_source') -%} + {%- set sources = ['Apple TV', 'Plex', 'YouTube', 'Netflix', '10 play', '7plus', '9Now', 'MUBI', 'ABC iview', 'Prime Video', 'Vimeo', 'Spotify', 'Radio'] -%} + {%- if current_source is not none -%} + {% set sources = sources + [current_source] -%} + {%- endif %} + {%- set sources = sources + (state_attr('media_player.denon_avr_x1600h_heos', 'source_list') or []) -%} + {%- set sources = sources + (state_attr('media_player.denon_avr_x1600h', 'source_list') or []) -%} + + {{- sources | sort | unique | list -}} + +media_player: + - platform: universal + name: Living Room Spotify (bjeanes) # create a media player that is only "on"/"playing"/etc when it is playing in the living room + children: + - media_player.spotify_bjeanes + state_template: > + {% if is_state_attr('media_player.spotify_bjeanes', 'source', 'Denon AVR-X1600H') %} + {{ states(media_player.spotify_bjeanes) }} + {% else %} + idle + {% endif %} + commands: {} + - platform: universal + # unique_id: media_player_living_room_universal + name: Living Room Media Player + children: + - media_player.denon_avr_x1600h_heos + - media_player.living_room_apple_tv + - media_player.living_room_tv_webos + - media_player.living_room_tv_homekit + - media_player.denon_avr_x1600h + - media_player.living_room_spotify_bjeanes + state_template: > + {{ states(states('sensor.current_living_room_media_player')) }} + commands: {} + attributes: + active_child: sensor.current_living_room_media_player + is_volume_muted: sensor.current_living_room_media|is_volume_muted + volume_level: sensor.current_living_room_media|volume_level + source_list: sensor.current_living_room_media_player_source|source_list + device_class: sensor.current_living_room_media|device_class + +automation: + - id: turn_on_apple_tv_on_source + trigger: + - platform: state + entity_id: media_player.living_room_media_player + attribute: "source" + to: "Apple TV" + action: + - service: media_player.turn_on + target: + area_id: living_room + - service: remote.turn_on + target: + entity_id: remote.living_room_apple_tv + + - id: adjust_denon_volume + alias: Automatically adjust Denon volume + mode: restart + trigger: + - platform: state + entity_id: media_player.denon_avr_x1600h + attribute: "source" + - platform: state + entity_id: media_player.denon_avr_x1600h_heos + attribute: "source" + - platform: state + entity_id: media_player.living_room_media_player + attribute: "source" + action: + - variables: + current_volume_level: "{{ state_attr('media_player.denon_avr_x1600h', 'volume_level') }}" + new_volume_level: >- + # TODO model as a dictionary https://community.home-assistant.io/t/remember-volume-levels-of-each-source-for-a-media-player-to-automate-restoring/416749/6?u=bjeanes + {% set volumes = state_attr('sensor.living_room_media_player_source_volumes', 'volumes') or [] %} + {% set specific_source = state_attr('media_player.living_room_media_player', 'source') %} + {% set general_source = state_attr('media_player.denon_avr_x1600h', 'source') %} + {% set ns = namespace(volume_level=None) %} + {% for v in volumes %} + {% if v.source == specific_source %} + {% set ns.volume_level = v.volume_level %} + {% endif %} + {% endfor %} + + {% if ns.volume_level == None %} + {% for v in volumes %} + {% if v.source == general_source %} + {% set ns.volume_level = v.volume_level %} + {% endif %} + {% endfor %} + {% endif %} + + {% if ns.volume_level == None %} + {% if general_source == "HEOS Music" %} + {% set ns.volume_level = 0.4 %} + {% else %} + {% set ns.volume_level = 0.6 %} + {% endif %} + {% endif %} + + {{ ns.volume_level }} + - repeat: + sequence: + - service: media_player.volume_set + data: + volume_level: "{{ new_volume_level }}" + target: + entity_id: media_player.denon_avr_x1600h + - delay: 2 # seconds + until: "{{ current_volume_level == new_volume_level or not is_state_attr('media_player.denon_avr_x1600h', 'volume_level', current_volume_level) }}" + - id: manage_background_playlist + alias: Manage Background playlist + trigger: + - platform: state + entity_id: sensor.background_playlist + condition: + # rule out error states (HA bootup, reloading, etc) + - "{{ trigger.to_state.state not in ['unavailable', 'unknown'] }}" + + # has to have been off or describing what is already playing + - "{{ trigger.from_state.state in ['off', states('sensor.current_living_room_media_player_source')] }}" + + # We be turning off unless the should_play_background_music is true + - "{{ trigger.to_state.state == 'off' or is_state('binary_sensor.should_play_background_music', 'on') }}" + action: + - variables: + player_is_off_like: >- + {{ + ( + is_state('media_player.denon_avr_x1600h', 'off') or + ( + is_state_attr('media_player.denon_avr_x1600h', 'source', 'HEOS Music') and + is_state('media_player.denon_avr_x1600h_heos', 'idle') + ) + ) + }} + - choose: + - conditions: + - "{{ trigger.to_state.state == 'off' }}" + sequence: + - service: media_player.turn_off + target: + area_id: living_room + - conditions: + - "{{ trigger.from_state != 'off' or player_is_off_like }}" + sequence: + - service: media_player.select_source + data: + source: "{{ trigger.to_state.state }}" + target: + entity_id: media_player.denon_avr_x1600h_heos # TODO: make the universal media player capable of receiving this + +sensor: + - platform: rest + resource: https://airnet.org.au/rest/stations/3rrr/guides/fm + name: RRR Now Playing + value_template: >- + {{ value_json + | selectattr('day', 'eq', now().isoweekday() | string) + | reverse + | selectattr('start', 'lt', now().strftime('%H:%M:%S')) + | map(attribute='name') + | first + }} + - platform: rest + resource: https://airnet.org.au/rest/stations/3pbs/guides/fm + name: PBS Now Playing + value_template: >- + {{ value_json + | selectattr('day', 'eq', now().isoweekday() | string) + | reverse + | selectattr('start', 'lt', now().strftime('%H:%M:%S')) + | map(attribute='name') + | first + }} + - platform: rest + resource: https://program.abcradio.net.au/api/v1/programitems/triplej/live.json + name: JJJ Now Playing + value_template: >- + {{ value_json.now.title }} + - platform: rest + resource: https://program.abcradio.net.au/api/v1/programitems/doublej/live.json + name: JJ Now Playing + value_template: >- + {{ value_json.now.title }} + - platform: rest + resource: https://program.abcradio.net.au/api/v1/programitems/jazz/live.json + name: ABC Jazz Now Playing + value_template: >- + {{ value_json.now.title }} + + - platform: schedule_state # https://github.com/aneeshd/schedule_state + name: Background Playlist + refresh: "5:00:00" + default_state: "off" + events: + - state: ABC Jazz (Jazz Music) # Default background music + start: "8:00:00" + end: "23:00:00" + + - state: Triple R 102.7 (Variety) # https://www.rrr.org.au/explore/programs/radiotherapy + start: "10:00:00" + end: "11:00:00" + condition: + condition: time + weekday: [sun] + + - state: Triple R 102.7 (Variety) # https://www.rrr.org.au/explore/programs/einstein-a-go-go + start: "11:00:00" + end: "12:00:00" + condition: + condition: time + weekday: [sun] + + - state: Triple R 102.7 (Variety) + condition: + condition: state + entity_id: sensor.rrr_now_playing + state: "On The Blower" + + - state: triple j 107.5 (Alternative Rock) + condition: + condition: state + entity_id: sensor.jjj_now_playing + state: "Science with Dr Karl" + + - state: triple j 107.5 (Alternative Rock) + condition: + condition: state + entity_id: sensor.jjj_now_playing + state: "Hack" + + # ... + + - state: "off" # must be last so that it overrides everything else when its conditions are true + condition: + - condition: state + entity_id: binary_sensor.should_play_background_music + state: "off" + +homekit: + - name: living_room_media_centre + port: 21242 + mode: accessory + filter: + include_entities: + - media_player.living_room_media_player diff --git a/config/packages/media_server.yaml b/config/packages/media_server.yaml new file mode 100644 index 0000000..2622c57 --- /dev/null +++ b/config/packages/media_server.yaml @@ -0,0 +1,23 @@ +template: + - sensor: + - unique_id: nzbget_speed_kilobytes_per_sec + name: "NZBGet Speed" + unit_of_measurement: kB/s + state: | + {% if states('sensor.nzbget_speed') is number %} + {{ states('sensor.nzbget_speed') / 1000.0 }} + {% else %} + {{ states('sensor.nzbget_speed') }} + {% endif %} + +sensor: + - platform: rtorrent + url: "https://rutorrent.home.bjeanes.com/RPC2" + monitored_variables: + - "current_status" + - "download_speed" + - "upload_speed" + - "all_torrents" + - "uploading_torrents" + - "downloading_torrents" + - "active_torrents" diff --git a/config/packages/misc.yaml b/config/packages/misc.yaml new file mode 100644 index 0000000..ab0d3f1 --- /dev/null +++ b/config/packages/misc.yaml @@ -0,0 +1,60 @@ +anniversaries: + sensors: + - name: Anniversary + date: "2007-08-09" + - name: Wedding Anniversary + date: "2010-12-07" + - name: Bo's Birthday + date: "1987-06-24" + - name: Ri's Birtthday + date: "1988-02-01" + - name: Ri's Mum's Birthday + date: "1960-03-19" + - name: Haley's Birthday + date: "2009-08-03" + - name: Archie's Birthday + date: "2017-10-24" + - name: Misty's Birthday + date: "2016-04-24" + - name: Bo's Mum's Birthday + date: "1965-01-20" + - name: Bo's Dad's Birthday + date: "1952-10-04" + - name: Chela's Birthday + date: "1996-06-16" + - name: Jacob's Birthday + date: "1993-06-22" + - name: Lucia's Birthday + date: "2005-10-26" + - name: Kian's Birthday + date: "1998-07-27" + - name: Andy's Birthday + date: "1987-02-17" + - name: Jordon's Birthday + date: "02-19" + - name: Kate's Birthday + date: "03-20" + - name: Nick's Birthday + date: "1983-03-24" + - name: Anthony's Birthday + date: "1983-11-19" + - name: Mischa's Birthday + date: "1988-01-18" + - name: Suzanne's Birthday + date: "1988-04-20" + - name: Richy's Birthday + date: "1997-10-26" + - name: Bo's Nan's Birthday + date: "07-05" + - name: Shahron's Birthday + date: "1962-07-23" + - name: Valentin's Birthday + date: "03-28" + - name: Odin's Birthday + date: "06-07" + - name: Ellie's Birthday + date: "06-17" + - name: Tyson's Birthday + date: "05-05" + - name: Alex Charry's Birthday + date: "08-06" diff --git a/config/packages/offices.yaml b/config/packages/offices.yaml new file mode 100644 index 0000000..22902c3 --- /dev/null +++ b/config/packages/offices.yaml @@ -0,0 +1,71 @@ +# If door opens when sun is down, turn lights on +# If sun sets and door is open or presense detected, turn lights on +# If lights on but no presence for one hour, turn lights off +# When lights turned off, turn off desk and couch plugs +# When lights turned on, turn on desk and couch plugs +# When bo leaves home, turn off desk plug +# When everybody leaves home, turn off couch plug +automation: + - id: a1459b6c502b7d9df65a101dd31c9c55f164388c + alias: Turn on Bo's office when door opened + trigger: + - platform: state + entity_id: binary_sensor.bo_s_office_door_contact + from: "off" + to: "on" + action: + # - if: + # - "{{ is_state('sun.sun', 'below_horizon') }}" + # then: + - service: light.turn_on + data: + transition: 0.25 + color_temp: 500 + brightness_pct: 100 + target: + area_id: bo_s_office + - service: switch.turn_on + target: + area_id: bo_s_office + + - id: 2d1034acdee3afde7b67224b4898bd87b5cd356c + alias: Turn on Ri's office when door opened + trigger: + - platform: state + entity_id: binary_sensor.ri_s_office_door_contact + from: "off" + to: "on" + action: + - if: + - "{{ is_state('sun.sun', 'below_horizon') }}" + then: + - service: light.turn_on + data: + transition: 0.25 + color_temp: 500 + brightness_pct: 100 + target: + area_id: ri_s_office + - service: switch.turn_on + target: + area_id: ri_s_office + + - id: b3f8aa9d20fee297accbd6aad27ba29c28aa02dc + alias: Turn off offices when in bed + trigger: + - platform: state + entity_id: group.everyone_in_bed + to: "on" + for: + minutes: 5 + action: + - service: light.turn_off + target: + area_id: + - bo_s_office + - ri_s_office + - service: switch.turn_off + target: + area_id: + - bo_s_office + - ri_s_office diff --git a/config/packages/presence.yaml b/config/packages/presence.yaml new file mode 100644 index 0000000..10ebc6c --- /dev/null +++ b/config/packages/presence.yaml @@ -0,0 +1,169 @@ +# TODO: One of these for each ID that ESPresense uses for our devices + a group each for ri's and mine + a template sensor to pick from each group the one which is most recently updated. +sensor: + # One entry for each beacon you want to track + - platform: mqtt_room + device_id: "roomAssistant:f76c2617-3d2e-4e35-a669-606e13162a68" + name: Room > Bo > Room Assistant + state_topic: "espresense/rooms" + timeout: 30 + away_timeout: 120 + + - platform: mqtt_room + device_id: "apple:1007:11-8" + name: Room > Bo > Apple + state_topic: "espresense/rooms" + timeout: 30 + away_timeout: 120 + + - platform: mqtt_room + device_id: "apple:iphone13-1" + name: Room > Bo > Apple (Expanded) + state_topic: "espresense/rooms" + timeout: 30 + away_timeout: 120 + + - platform: mqtt_room + device_id: "roomAssistant:95397a15-89d3-44f9-be0a-a30e7b2e4381" + name: Room > Ri > Room Assistant + state_topic: "espresense/rooms" + timeout: 30 + away_timeout: 120 + + - platform: mqtt_room + device_id: "apple:1006:10-12" + name: Room > Ri > Apple + state_topic: "espresense/rooms" + timeout: 30 + away_timeout: 120 + + - platform: mqtt_room + device_id: "apple:iphone10-3" + name: Room > Ri > Apple (Expanded) + state_topic: "espresense/rooms" + timeout: 30 + away_timeout: 120 + +group: + room_bo_phone: + entities: + - sensor.room_bo_room_assistant + - sensor.room_bo_apple + - sensor.room_bo_apple_expanded + room_ri_phone: + entities: + - sensor.room_ri_room_assistant + - sensor.room_ri_apple + - sensor.room_ri_apple_expanded + room_phones: + entities: + - sensor.room_bo_phone + - sensor.room_ri_phone + +template: + - sensor: + - unique_id: room_bo_phone + state: >- + {{ states(state_attr('sensor.template_room_bo_phone', 'entity_id') | string) or 'not_home' }} + attributes: + entity_id: >- + {% set identifiers = expand('group.room_bo_phone') %} + {% set close_updates = identifiers + | selectattr('state', 'ne', 'not_home') + | sort(attribute='attributes.distance') + | selectattr('last_updated', 'gt', now() - timedelta(seconds=30)) + | list %} + {% set recent_updates = identifiers + | sort(attribute='last_updated', reverse=True) + | list %} + {% set most_recent_home = recent_updates + | selectattr('state', 'ne', 'not_home') + | list %} + {% set candidates = close_updates + most_recent_home + recent_updates %} + {{ candidates | map(attribute='entity_id') | first }} + distance: >- + {{ state_attr(state_attr('sensor.template_room_bo_phone', 'entity_id') | string, 'distance') }} + - unique_id: room_ri_phone + state: >- + {{ states(state_attr('sensor.template_room_ri_phone', 'entity_id') | string) or 'not_home' }} + attributes: + entity_id: >- + {% set identifiers = expand('group.room_ri_phone') %} + {% set close_updates = identifiers + | selectattr('state', 'ne', 'not_home') + | sort(attribute='attributes.distance') + | selectattr('last_updated', 'gt', now() - timedelta(seconds=30)) + | list %} + {% set recent_updates = identifiers + | sort(attribute='last_updated', reverse=True) + | list %} + {% set most_recent_home = recent_updates + | selectattr('state', 'ne', 'not_home') + | list %} + {% set candidates = close_updates + most_recent_home + recent_updates %} + {{ candidates | map(attribute='entity_id') | first }} + distance: >- + {{ state_attr(state_attr('sensor.template_room_ri_phone', 'entity_id') | string, 'distance') }} + + - trigger: + - platform: time_pattern + seconds: "/3" + binary_sensor: + - unique_id: bos_office_is_occupied + name: Bo's Office Is Occupied + state: | + {{ is_state('sensor.template_room_bo_phone', 'bo_s_office') or is_state('sensor.template_room_ri_phone', 'bo_s_office') }} + icon: | + {% if is_state("binary_sensor.bo_s_office_is_occupied", "on") %} + mdi:person + {% else %} + mdi:person-outline + {% endif %} + device_class: occupancy + + - unique_id: ris_office_is_occupied + name: Ri's Office Is Occupied + state: | + {{ is_state('sensor.template_room_bo_phone', 'ri_s_office') or is_state('sensor.template_room_ri_phone', 'ri_s_office') }} + icon: | + {% if is_state("binary_sensor.ri_s_office_is_occupied", "on") %} + mdi:person + {% else %} + mdi:person-outline + {% endif %} + device_class: occupancy + + - unique_id: bedroom_is_occupied + name: Bedroom Is Occupied + state: | + {{ is_state('sensor.template_room_bo_phone', 'bedroom') or is_state('sensor.template_room_ri_phone', 'bedroom') }} + icon: | + {% if is_state("binary_sensor.bedroom_is_occupied", "on") %} + mdi:person + {% else %} + mdi:person-outline + {% endif %} + device_class: occupancy + + - unique_id: living_room_is_occupied + name: Living Room Is Occupied + state: | + {{ is_state('sensor.template_room_bo_phone', 'living_room') or is_state('sensor.template_room_ri_phone', 'living_room') }} + icon: | + {% if is_state("binary_sensor.living_room_is_occupied", "on") %} + mdi:person + {% else %} + mdi:person-outline + {% endif %} + device_class: occupancy + + - unique_id: lounge_room_is_occupied + name: Lounge Room Is Occupied + state: | + {{ is_state('sensor.template_room_bo_phone', 'lounge_room') or is_state('sensor.template_room_ri_phone', 'lounge_room') }} + icon: | + {% if is_state("binary_sensor.lounge_room_is_occupied", "on") %} + mdi:person + {% else %} + mdi:person-outline + {% endif %} + device_class: occupancy diff --git a/config/packages/vacuum.yaml b/config/packages/vacuum.yaml new file mode 100644 index 0000000..7a31048 --- /dev/null +++ b/config/packages/vacuum.yaml @@ -0,0 +1,25 @@ +camera: + - platform: xiaomi_cloud_map_extractor + host: !secret xiaomi_vacuum_host + token: !secret xiaomi_vacuum_token + username: !secret xiaomi_cloud_username + password: !secret xiaomi_cloud_password + country: "sg" + name: "Vacuum map" + draw: ["all"] + +template: + - sensor: + - unique_id: robot_vacuum_battery_level + state: | + {{ state_attr('vacuum.robot_vacuum', 'battery_level') | int }} + unit_of_measurement: "%" + device_class: battery + state_class: measurement + name: Robot Vacuum Battery Level + binary_sensor: + - unique_id: robot_vacuum_charging + name: Robot Vacuum Charging + device_class: battery_charging + state: | + {{ is_state_attr('vacuum.robot_vacuum', 'status', 'Charging') }} diff --git a/config/packages/work.yaml b/config/packages/work.yaml new file mode 100644 index 0000000..87c583a --- /dev/null +++ b/config/packages/work.yaml @@ -0,0 +1,34 @@ +calendar: + - platform: ics_calendar + calendars: + - name: "On-call" + url: !secret oncall_schedule_url + includeAllDay: true + days: 30 + +automation: + - id: remind_bo_to_take_laptop_when_oncall + trigger: + - platform: state + entity_id: cover.front_gate + from: "closed" + to: "open" + - platform: state + entity_id: cover.front_gate + from: "closed" + to: "opening" + - platform: event + event_type: homekit_state_change + event_data: + entity_id: cover.front_gate + service: open_cover + condition: >- + {{ is_state('calendar.on_call', 'on') or is_state('calendar.ical_on_call', 'on') }} + action: + - service: notify.mobile_app_bos_iphone + data: + message: You are on-call! Bring your laptop + title: Bring laptop! + data: + push: + interruption-level: time-sensitive diff --git a/config/scenes.yaml b/config/scenes.yaml new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/config/scenes.yaml @@ -0,0 +1 @@ +[] diff --git a/config/scripts.yaml b/config/scripts.yaml new file mode 100644 index 0000000..7157a14 --- /dev/null +++ b/config/scripts.yaml @@ -0,0 +1,48 @@ +refill_tent_humidifier: + sequence: + - service: scene.create + data: + snapshot_entities: + - automation.turn_on_tent_humidifier + - switch.tent_humidifier_local + - timer.humidifier_time_till_refill + scene_id: snapshot_humidifier_before_refilling + - type: turn_off + device_id: 4f8a04a40876b2a1914ea8d004b6aac5 + entity_id: switch.tent_humidifier_local + domain: switch + - service: automation.turn_off + data: {} + target: + entity_id: automation.turn_on_tent_humidifier + - service: timer.cancel + data: {} + target: + entity_id: timer.humidifier_time_till_refill + - delay: + hours: 0 + minutes: 5 + seconds: 0 + milliseconds: 0 + - service: input_datetime.set_datetime + data: + timestamp: "{{ now().timestamp() }}" + target: + entity_id: input_datetime.tent_humidifier_refilled_at + - service: timer.start + data: + duration: "{{ states('counter.humidifier_run_time_since_refill') }}" + target: + entity_id: timer.humidifier_time_till_refill + - service: counter.reset + data: {} + target: + entity_id: counter.humidifier_run_time_since_refill + - service: timer.pause + data: {} + target: + entity_id: timer.humidifier_time_till_refill + - scene: scene.snapshot_humidifier_before_refilling + mode: single + alias: Refill tent humidifier + icon: mdi:waves-arrow-up diff --git a/config/watchman_report.txt b/config/watchman_report.txt new file mode 100644 index 0000000..52e6ddc --- /dev/null +++ b/config/watchman_report.txt @@ -0,0 +1,98 @@ +-== Watchman Report ==- + +-== Congratulations, all 28 services from your config are available! + +-== Missing 85 entity(ies) from 276 found in your config: ++--------------------------------------------------------------+----------------------+----------------------------------------------------------------------------------+ +| Entity ID | State | Location | ++--------------------------------------------------------------+----------------------+----------------------------------------------------------------------------------+ +| scene.snapshot_humidifier_before_refilling | missing | scripts.yaml:45 | +| switch.is_off | missing | esphome/front-gate.yaml:80,113,130 | +| binary_sensor.is_on | missing | esphome/front-gate.yaml:114,122 | +| binary_sensor.is_off | missing | esphome/front-gate.yaml:131 | +| sensor.octoprint_current_state | unavail | packages/3d_printing.yaml:28,36 | +| sensor.room_bo_phone | missing | packages/presence.yaml:59 | +| sensor.room_ri_phone | missing | packages/presence.yaml:60 | +| sensor.tent_wattage | unavail | packages/grow.yaml:33,301,324,390,408 | +| sensor.tent_temperature | missing | packages/grow.yaml:43 | +| sensor.tent_temperature_cached | unavail | packages/grow.yaml:43,59 | +| sensor.tent_humidity | missing | packages/grow.yaml:51 | +| sensor.tent_svp | unavail | packages/grow.yaml:63,71,84 | +| sensor.tent_humidity_cached | unknown | packages/grow.yaml:72,265,269,291,304 | +| sensor.tent_avp | unavail | packages/grow.yaml:76,85 | +| sensor.tent_vpd | unavail | packages/grow.yaml:89,258,284 | +| switch.tent_power_strip_grow_lights | missing | packages/grow.yaml:100,120,199,212,225 | +| switch.tent_cam_night_vision | unavail | packages/grow.yaml:111,131 | +| sensor.tent_reservoir_ph | missing | packages/grow.yaml:233,240 | +| switch.tent_cam_focus | unavail | packages/grow.yaml:330,339 | +| sensor.ri_s_phone | missing | packages/home.yaml:46,54 | +| input_boolean.turn_ | missing | packages/home.yaml:94 | +| sensor.bos_iphone_activity | missing | packages/gate.yaml:65,68 | +| media_player.apple_tv | missing | packages/media_centre.yaml:29,32,90,109,112,113 | +| media_player.living_room_tv_homekit | unavail | packages/media_centre.yaml:172 | +| sensor.current_living_room_media | missing | packages/media_centre.yaml:180,181,183 | +| sensor.eagle_200_net_meter_energy_delivered_minus_received | missing | .storage/lovelace:928 | +| sensor.tent_reservoir_ec_us | missing | .storage/lovelace.lovelace_gardens:115,272,737 | +| sensor.tent_cam_battery_level | unavail | .storage/lovelace.lovelace_gardens:140 | +| sensor.tent_cam_battery_temperature | unavail | .storage/lovelace.lovelace_gardens:144 | +| sensor.tent_cam_light_level | unavail | .storage/lovelace.lovelace_gardens:148 | +| switch.tent_power_plug | unavail | .storage/lovelace.lovelace_gardens:175 | +| sensor.tent_reservoir_temperature | missing | .storage/lovelace.lovelace_gardens:264,725 | +| input_number.tent_temperature | missing | .storage/lovelace.lovelace_gardens:586 | +| sensor.bendigo_temp | missing | .storage/lovelace.lovelace_gardens:678 | +| sensor.bendigo_humidity | missing | .storage/lovelace.lovelace_gardens:696 | +| sensor.tent_hhcc_1_illuminance | missing | .storage/lovelace.lovelace_gardens:765 | +| sensor.tent_hhcc_2_illuminance | missing | .storage/lovelace.lovelace_gardens:769 | +| sensor.tent_hhcc_1_moisture | missing | .storage/lovelace.lovelace_gardens:780 | +| sensor.tent_hhcc_2_moisture | missing | .storage/lovelace.lovelace_gardens:784 | +| sensor.tent_hhcc_1_temperature | missing | .storage/lovelace.lovelace_gardens:795 | +| sensor.tent_hhcc_2_temperature | missing | .storage/lovelace.lovelace_gardens:799 | +| sensor.tent_hhcc_1_soil_conductivity | missing | .storage/lovelace.lovelace_gardens:810 | +| sensor.tent_hhcc_2_soil_conductivity | missing | .storage/lovelace.lovelace_gardens:814 | +| button.garden_shed_ble_relay_restart | missing | .storage/lovelace.lovelace_gardens:959 | +| binary_sensor.garden_shed_ble_relay_status | missing | .storage/lovelace.lovelace_gardens:963 | +| sensor.garden_shed_ble_relay_wifi_signal | missing | .storage/lovelace.lovelace_gardens:968 | +| sensor.garden_shed_ble_relay_uptime_human_readable | missing | .storage/lovelace.lovelace_gardens:972 | +| button.octoprint_stop_job | unavail | .storage/lovelace.3d_printing:65 | +| binary_sensor.octoprint_printing | unavail | .storage/lovelace.3d_printing:76,99,121,251 | +| button.octoprint_pause_job | unavail | .storage/lovelace.3d_printing:85 | +| button.octoprint_resume_job | unavail | .storage/lovelace.3d_printing:91 | +| sensor.octoprint_start_time | unknown | .storage/lovelace.3d_printing:147 | +| sensor.octoprint_estimated_finish_time | unknown | .storage/lovelace.3d_printing:154 | +| sensor.octoprint_actual_bed_temp | unavail | .storage/lovelace.3d_printing:178,265 | +| sensor.octoprint_target_bed_temp | unavail | .storage/lovelace.3d_printing:182,269 | +| sensor.octoprint_target_tool0_temp | unavail | .storage/lovelace.3d_printing:204,208,277 | +| binary_sensor.octoprint_printing_error | unavail | .storage/lovelace.3d_printing:218,223 | +| sensor.octoprint_actual_tool0_temp | unavail | .storage/lovelace.3d_printing:273 | +| media_player.plex_plex_for_apple_tv_living_room | unavail | .storage/lovelace.lovelace_servers:23 | +| sensor.nas_cpu_load_averarge_5_min | missing | .storage/lovelace.lovelace_servers:126 | +| sensor.nas_cpu_load_averarge_15_min | missing | .storage/lovelace.lovelace_servers:129 | +| sensor.nas_network_down | missing | .storage/lovelace.lovelace_servers:135,333 | +| sensor.nas_network_up | missing | .storage/lovelace.lovelace_servers:138,336 | +| binary_sensor.nas_update_available | missing | .storage/lovelace.lovelace_servers:144 | +| sensor.nas_memory_size | missing | .storage/lovelace.lovelace_servers:346 | +| sensor.home_assistant_v2_db | missing | .storage/lovelace.lovelace_servers:426 | +| sensor.aircast_cpu_percent | missing | .storage/lovelace.lovelace_servers:433 | +| sensor.deconz_cpu_percent | missing | .storage/lovelace.lovelace_servers:434 | +| sensor.frigate_nvr_full_access_cpu_percent | missing | .storage/lovelace.lovelace_servers:437 | +| sensor.influxdb_cpu_percent | missing | .storage/lovelace.lovelace_servers:440 | +| sensor.sqlite_web_cpu_percent | unavail | .storage/lovelace.lovelace_servers:444 | +| sensor.vaultwarden_bitwarden_cpu_percent | missing | .storage/lovelace.lovelace_servers:446 | +| sensor.vaultwarden_bitwarden_memory_percent | missing | .storage/lovelace.lovelace_servers:456 | +| sensor.sqlite_web_memory_percent | unavail | .storage/lovelace.lovelace_servers:458 | +| sensor.influxdb_memory_percent | missing | .storage/lovelace.lovelace_servers:462 | +| sensor.frigate_nvr_full_access_memory_percent | missing | .storage/lovelace.lovelace_servers:465 | +| sensor.deconz_memory_percent | missing | .storage/lovelace.lovelace_servers:468 | +| sensor.aircast_memory_percent | missing | .storage/lovelace.lovelace_servers:469 | +| sensor.speedtest_download | unavail | .storage/lovelace.lovelace_servers:580 | +| sensor.speedtest_upload | unavail | .storage/lovelace.lovelace_servers:587 | +| sensor.speedtest_ping | unavail | .storage/lovelace.lovelace_servers:594 | +| sensor.hl_l2305_black_toner_remaining | missing | .storage/lovelace.lovelace_servers:610 | +| sensor.hl_l2305_drum_remaining_life | missing | .storage/lovelace.lovelace_servers:611 | +| sensor.hl_l2305_page_counter | missing | .storage/lovelace.lovelace_servers:612 | +| sensor.hl_l2305_status | missing | .storage/lovelace.lovelace_servers:613 | ++--------------------------------------------------------------+----------------------+----------------------------------------------------------------------------------+ + +-== Report created on 11 May 2022 09:50:54 +-== Parsed 62 files in 0.76s., ignored 160 files +-== Generated in: 0.02s. Validated in: 0.00s. diff --git a/config/webostv.conf b/config/webostv.conf new file mode 100644 index 0000000000000000000000000000000000000000..70d8a2604b989f111d2cc00d7e750579b3220424 GIT binary patch literal 12288 zcmeI$Jxjwt7zgl6qM|}Mw+>y7)`EhDyw?nhsbr8=)HZ{i$~Cz{wJ)ft=%ns0Lj69j zehWW>qoYZiL8nd*%KssE&)tRR4u0ER^R(WJ1?!Hk20UgaStF7}_8B9DC|OI=G^C_o z$i`_(=kr1#YVA2kKZ#6ZLSyu7WiiYJ82vqd5spU`K>K>!~0{ws`caQ z=C-_)_X-l}4I^=Tec4ZL^=&?mN7H#b+o-K)gY<5{oO0H;;0uNaj$`qz8C6WnG7Yn$TehX!nmbWfle1*{PUuI{ qAs_$&2tWV=5P$##AOHafKmY;|_>%%uDM{a67i6lGS7!6sbHNu2idm8X literal 0 HcmV?d00001 diff --git a/config/zigbee2mqtt/configuration.yaml b/config/zigbee2mqtt/configuration.yaml new file mode 100644 index 0000000..4985ff8 --- /dev/null +++ b/config/zigbee2mqtt/configuration.yaml @@ -0,0 +1 @@ +homeassistant: true diff --git a/config/zigbee2mqtt/state.json b/config/zigbee2mqtt/state.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/config/zigbee2mqtt/state.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/esphome/.gitignore b/esphome/.gitignore new file mode 100644 index 0000000..6ce782d --- /dev/null +++ b/esphome/.gitignore @@ -0,0 +1,11 @@ +# Gitignore settings for ESPHome +# This is an example and may include too much for your use-case. +# You can modify this file to suit your needs. +/.esphome/ +**/.pioenvs/ +**/.piolibdeps/ +**/lib/ +**/src/ +**/platformio.ini +/secrets.yaml +build/ diff --git a/esphome/athom-plug-55869a.yaml b/esphome/athom-plug-55869a.yaml new file mode 100644 index 0000000..f3a05e0 --- /dev/null +++ b/esphome/athom-plug-55869a.yaml @@ -0,0 +1,10 @@ +substitutions: + node_name: "athom-plug-55869a" + friendly_name: "Washing Machine Plug" + +packages: + base: !include common/base.yaml + plug: !include common/athom-plug.yaml + +wifi: + use_address: 10.10.30.157 \ No newline at end of file diff --git a/esphome/athom-plug-5586a8.yaml b/esphome/athom-plug-5586a8.yaml new file mode 100644 index 0000000..893b158 --- /dev/null +++ b/esphome/athom-plug-5586a8.yaml @@ -0,0 +1,10 @@ +substitutions: + node_name: "athom-plug-5586a8" + friendly_name: "Tent Plug" + +packages: + base: !include common/base.yaml + plug: !include common/athom-plug.yaml + +wifi: + use_address: 10.10.30.171 \ No newline at end of file diff --git a/esphome/athom-plug-ce0b40.yaml b/esphome/athom-plug-ce0b40.yaml new file mode 100644 index 0000000..1330ad4 --- /dev/null +++ b/esphome/athom-plug-ce0b40.yaml @@ -0,0 +1,10 @@ +substitutions: + name: "athom-plug-ce0b40" +packages: + athom.smart-plug: github://athom-tech/athom-configs/athom-smart-plug.yaml +esphome: + name_add_mac_suffix: false + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password diff --git a/esphome/athom-plug-ceed51.yaml b/esphome/athom-plug-ceed51.yaml new file mode 100644 index 0000000..28d43da --- /dev/null +++ b/esphome/athom-plug-ceed51.yaml @@ -0,0 +1,11 @@ +substitutions: + node_name: "athom-plug-ceed51" + friendly_name: "Plug ceed51" + +esphome: + platform: ESP8266 + board: esp8285 + +packages: + base: !include common/base.yaml + plug: !include common/athom-plug.yaml diff --git a/esphome/athom-plug-cf4329.yaml b/esphome/athom-plug-cf4329.yaml new file mode 100644 index 0000000..a706766 --- /dev/null +++ b/esphome/athom-plug-cf4329.yaml @@ -0,0 +1,10 @@ +substitutions: + node_name: "athom-plug-cf4329" + friendly_name: "NAS + TumTum Plug" + +packages: + base: !include common/base.yaml + plug: !include common/athom-plug.yaml + +wifi: + use_address: 10.10.30.141 \ No newline at end of file diff --git a/esphome/athom-smart-plug-v2-3fea2b.yaml b/esphome/athom-smart-plug-v2-3fea2b.yaml new file mode 100644 index 0000000..22430d0 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3fea2b.yaml @@ -0,0 +1,14 @@ +substitutions: + device_name: athom-smart-plug-v2-3fea2b + friendly_name: Ri's Desk Plug + relay_restore_mode: RESTORE_DEFAULT_ON +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name_add_mac_suffix: false + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + use_address: 10.10.30.114 + fast_connect: true diff --git a/esphome/athom-smart-plug-v2-3feafe.yaml b/esphome/athom-smart-plug-v2-3feafe.yaml new file mode 100644 index 0000000..1cd8cf7 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3feafe.yaml @@ -0,0 +1,13 @@ +substitutions: + device_name: athom-smart-plug-v2-3feafe + friendly_name: Fridge Plug + relay_restore_mode: RESTORE_DEFAULT_ON +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name_add_mac_suffix: false + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password diff --git a/esphome/athom-smart-plug-v2-3fec6e.yaml b/esphome/athom-smart-plug-v2-3fec6e.yaml new file mode 100644 index 0000000..d2fa266 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3fec6e.yaml @@ -0,0 +1,14 @@ +substitutions: + device_name: athom-smart-plug-v2-3fec6e + relay_restore_mode: RESTORE_DEFAULT_ON + friendly_name: Bo's Office Plug +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name_add_mac_suffix: false + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + use_address: 10.10.30.156 diff --git a/esphome/athom-smart-plug-v2-3ff2fc.yaml b/esphome/athom-smart-plug-v2-3ff2fc.yaml new file mode 100644 index 0000000..ee0bc75 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3ff2fc.yaml @@ -0,0 +1,13 @@ +substitutions: + device_name: athom-smart-plug-v2-3ff2fc + friendly_name: Bo's Desk Plug + relay_restore_mode: RESTORE_DEFAULT_ON +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name_add_mac_suffix: false + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + use_address: 10.10.30.223 diff --git a/esphome/athom-smart-plug-v2-3ff494.yaml b/esphome/athom-smart-plug-v2-3ff494.yaml new file mode 100644 index 0000000..086ee35 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3ff494.yaml @@ -0,0 +1,13 @@ +substitutions: + device_name: athom-smart-plug-v2-3ff494 + name: athom-smart-plug-v2-3ff494 + friendly_name: Bo's Desk Plug +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name_add_mac_suffix: false + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password diff --git a/esphome/ble-gateway-1.yaml b/esphome/ble-gateway-1.yaml new file mode 100644 index 0000000..f13d35c --- /dev/null +++ b/esphome/ble-gateway-1.yaml @@ -0,0 +1,18 @@ +substitutions: + node_name: ble-gateway-1 + friendly_name: BLE Gateway 1 + +esphome: + platform: ESP32 + board: esp32dev + +packages: + base: !include common/base.yaml + ble: !include common/ble-gateway.yaml + +wifi: + use_address: 10.10.30.121 + +web_server: + version: 2 + include_internal: true diff --git a/esphome/ble-gateway-2.yaml b/esphome/ble-gateway-2.yaml new file mode 100644 index 0000000..f7c568d --- /dev/null +++ b/esphome/ble-gateway-2.yaml @@ -0,0 +1,209 @@ +substitutions: + node_name: ble-gateway-2 + friendly_name: Garden Shed BLE Gateway + +esphome: + platform: ESP32 + board: esp32dev + +packages: + base: !include common/base.yaml + ble: !include common/ble-gateway.yaml + +wifi: + use_address: 10.10.30.82 + +# JDY-08 +# https://amperkot.ru/static/3236/uploads/datasheets/JDY-08.pdf +# [13:44:48][I][ble_client:085]: Attempting BLE connection to 7c:01:0a:43:4e:9e +# [13:44:49][D][ble_client_lambda:035]: Connected to BLE device +# [13:44:49][I][ble_client:161]: Service UUID: 0xFFE0 +# [13:44:49][I][ble_client:162]: start_handle: 0x1 end_handle: 0x9 +# [13:44:49][I][ble_client:341]: characteristic 0xFFE1, handle 0x3, properties 0x1c +# [13:44:49][I][ble_client:341]: characteristic 0xFFE2, handle 0x7, properties 0x1c +# [13:44:49][I][ble_client:161]: Service UUID: 0x1800 +# [13:44:49][I][ble_client:162]: start_handle: 0xa end_handle: 0x14 +# [13:44:49][I][ble_client:341]: characteristic 0x2A00, handle 0xc, properties 0x2 +# [13:44:49][I][ble_client:341]: characteristic 0x2A01, handle 0xe, properties 0x2 +# [13:44:49][I][ble_client:341]: characteristic 0x2A02, handle 0x10, properties 0xa +# [13:44:49][I][ble_client:341]: characteristic 0x2A05, handle 0x17, properties 0x20 +ble_client: + - mac_address: "7C:01:0A:43:4E:9E" + id: ph_260bd + on_connect: + then: + - wait_until: # wait until characteristic is discovered + lambda: |- + esphome::ble_client::BLEClient* client = id(ph_260bd); + + auto service_uuid = 0xFFE0; // can't get it off `sensor` because it is protected + auto char_uuid = 0xFFE1; // can't get it off `sensor` because it is protected + + esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid); + + return chr != nullptr; + - lambda: |- + ESP_LOGD("ble_client_lambda", "Connected to PH-260BD"); + + //esphome::ble_client::BLESensor* sensor = id(ph_260bd_sensor); + esphome::ble_client::BLEClient* client = id(ph_260bd); + + auto service_uuid = 0xFFE0; // can't get it off `sensor` because it is protected + auto char_uuid = 0xFFE1; // can't get it off `sensor` because it is protected + + esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid); + + if (chr == nullptr) { + ESP_LOGW("ble_client", "[0xFFE1] Characteristic not found. State update can not be written."); + } else { + unsigned char newVal[8] = { + 0x00, 0x03, 0x00, 0x00, + 0x00, 0x14, 0x44, 0x14 + }; + int status = esp_ble_gattc_write_char( + client->gattc_if, + client->conn_id, + chr->handle, + sizeof(newVal), + newVal, + ESP_GATT_WRITE_TYPE_NO_RSP, + ESP_GATT_AUTH_REQ_NONE + ); + + if (status) { + ESP_LOGW("ble_client", "Error sending write value to BLE gattc server, status=%d", status); + } + } + + /* + decltype(v)::foo = 1; // debug type of v by mis-casting it and looking at compiler error + */ + + on_disconnect: + then: + - lambda: |- + ESP_LOGD("ble_client", "Disconnected from PH-260BD"); + +sensor: + - platform: template + name: "Tent Reservoir EC (µS)" + id: ec_us + unit_of_measurement: "µS/cm" + accuracy_decimals: 0 + state_class: measurement + icon: mdi:water-opacity + filters: + - filter_out: nan + - throttle: 30s + + - platform: template + name: "Tent Reservoir Temperature" + id: temp + unit_of_measurement: "°C" + accuracy_decimals: 1 + state_class: measurement + device_class: temperature + filters: + - filter_out: nan + - throttle: 30s + + - platform: template + name: "Tent Reservoir pH" + id: ph + unit_of_measurement: "pH" + accuracy_decimals: 2 + state_class: measurement + icon: mdi:ph + filters: + - filter_out: nan + - throttle: 30s + + - platform: ble_client + ble_client_id: ph_260bd + id: ph_260bd_sensor + internal: true + service_uuid: FFE0 + characteristic_uuid: FFE1 + notify: true + + # The PH-260BD puts bytes onto the characteristic value which needs to be treated as text: + # + # [1] pry(main)> ['372e35312070480d0a32312e372020e284830d0a'].pack('H*') + # => "7.51 pH\r\n21.7 \xE2\x84\x83\r\n" + # [2] pry(main)> puts ['372e35312070480d0a32312e372020e284830d0a'].pack('H*') + # 7.51 pH + # 21.7 ℃ + # + # It alternates between putting the EC/TDS value alone (as a string, with units) and the pH and + # temperature together. Perhaps it can't fit all three in a single buffer. + # + # All values follow: number(s)/dot, space(s), unit, carriage return, new line + # + # This lambda parses the string and publishes each value+unit to the appropriate template sensor on each newline. + lambda: |- + ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", x.size(), x.size(), &x[0]); + + if (x.size() == 0) return NAN; + //decltype(parse_float)::foo= 1; + + std::string val_str = ""; + std::string val_unit = ""; + + // ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", x.size(), x.size(), &x[0]); + + // https://git.faked.org/jan/ph-260bd/-/blob/master/src/main.cpp#L7 + static int factorMsToPpm = 700; + + for (int i = 0; i < x.size(); i++) { + auto c = x[i]; + switch(c) { + case '\x30': // "0" + case '\x31': // "1" + case '\x32': // "2" + case '\x33': // "3" + case '\x34': // "4" + case '\x35': // "5" + case '\x36': // "6" + case '\x37': // "7" + case '\x38': // "8" + case '\x39': // "9" + case '\x2E': // "." + val_str += c; + break; + case '\x20': // " " + break; // proceed until we hit units + case '\x0d': // '\r' + break; // ignore + case '\x0a': // '\n' + // FIXME: Don't publish temperature when ppt is set as it drops the first char + + if (auto val = parse_number(val_str)) { + if (val_unit == "pH") { + id(ph).publish_state(*val); + } else if (val_unit == "\xE2\x84\x83") { // ℃ char + id(temp).publish_state(*val); + } else if (val_unit == "uS") { // microsiemens + id(ec_us)->publish_state(*val); + } else if (val_unit == "mS") { // millisiemens + id(ec_us)->publish_state(*val * 1000); + } else if (val_unit == "ppm") { // TDS parts per million + id(ec_us)->publish_state(*val / factorMsToPpm * 1000); + } else if (val_unit == "ppt") { // TDS parts per thousand + id(ec_us)->publish_state(*val / factorMsToPpm * 1000 * 1000); + + } else { + ESP_LOGW("ble_client.receive", "value received with unknown unit: [%s]", val_unit.c_str()); + } + } else { + ESP_LOGW("ble_client.receive", "value could not be parsed as float: [%s]", val_str.c_str()); + } + + val_unit = ""; + val_str = ""; + break; + default: + val_unit += c; + } + } + + return 0.0; // this sensor isn't actually used diff --git a/esphome/ble-gateway-3.yaml b/esphome/ble-gateway-3.yaml new file mode 100644 index 0000000..109e01e --- /dev/null +++ b/esphome/ble-gateway-3.yaml @@ -0,0 +1,14 @@ +substitutions: + node_name: ble-gateway-3 + friendly_name: BLE Gateway 3 + +esphome: + platform: ESP32 + board: esp32dev + +packages: + base: !include common/base.yaml + ble: !include common/ble-gateway.yaml + +wifi: + use_address: 10.10.30.120 diff --git a/esphome/common/athom-plug.yaml b/esphome/common/athom-plug.yaml new file mode 100644 index 0000000..0de743d --- /dev/null +++ b/esphome/common/athom-plug.yaml @@ -0,0 +1,117 @@ +# Athom Plug v1 (before Jan 21, 2022) +# +# GPIO# Component +# GPIO0 None +# GPIO1 None +# GPIO2 None +# GPIO3 Button1 +# GPIO4 BL0937 CF +# GPIO5 HLWBL CF1 +# GPIO9 None +# GPIO10 None +# GPIO12 HLWBL SELi +# GPIO13 LedLink +# GPIO14 Relay1 +# GPIO15 None +# GPIO16 None +# FLAG None + +esp8266: + board: esp8285 + restore_from_flash: true + +binary_sensor: + - platform: gpio + pin: + number: 3 + mode: INPUT_PULLUP + inverted: true + name: "${friendly_name} Power Button" + disabled_by_default: true + on_multi_click: + - timing: + - ON for at most 1s + - OFF for at least 0.2s + then: + - switch.toggle: relay + - timing: + - ON for at least 4s + then: + - button.press: restart_button + +sensor: + - platform: hlw8012 + sel_pin: + number: GPIO12 + inverted: true + cf_pin: GPIO4 + cf1_pin: GPIO5 + voltage_divider: 780 + current: + name: "${friendly_name} Current" + filters: + - calibrate_linear: + - 0.0000 -> 0.0110 # Relay off no load + - 0.0097 -> 0.0260 # Relay on no load + - 0.9270 -> 0.7570 + - 2.0133 -> 1.6330 + - 2.9307 -> 2.3750 + - 5.4848 -> 4.4210 + - 8.4308 -> 6.8330 + - 9.9171 -> 7.9830 + # Normalize for plug load + - lambda: if (x < 0.0260) return 0; else return (x - 0.0260); + voltage: + name: "${friendly_name} Voltage" + + power: + name: "${friendly_name} Wattage" + id: wattage + unit_of_measurement: W + filters: + - calibrate_linear: + - 0.0000 -> 0.5900 # Relay off no load + - 0.0000 -> 1.5600 # Relay on no load + - 198.5129 -> 87.8300 + - 434.2469 -> 189.5000 + - 628.6241 -> 273.9000 + - 1067.0067 -> 460.1000 + - 1619.8098 -> 699.2000 + - 2043.0282 -> 885.0000 + # Normalize for plug load + - lambda: if (x < 1.5600) return 0; else return (x - 1.5600); + energy: + id: energy + name: "${friendly_name} Energy Usage" + unit_of_measurement: Wh + change_mode_every: 1 # default 8 + update_interval: 5s + + - platform: total_daily_energy + name: "${friendly_name} Total Daily Energy" + power_id: wattage + unit_of_measurement: kWh + accuracy_decimals: 3 + filters: + - multiply: 0.001 + +switch: + - platform: gpio + name: "${friendly_name}" + pin: GPIO14 + id: relay + restore_mode: RESTORE_DEFAULT_ON + on_turn_on: + - light.turn_on: blue_led + + on_turn_off: + - light.turn_off: blue_led + +light: + - platform: status_led + name: "${friendly_name} Status LED" + id: blue_led + disabled_by_default: true + pin: + inverted: true + number: GPIO13 diff --git a/esphome/common/base.yaml b/esphome/common/base.yaml new file mode 100644 index 0000000..22e649e --- /dev/null +++ b/esphome/common/base.yaml @@ -0,0 +1,63 @@ +substitutions: + new_ota_password: !secret ota_password + +esphome: + name: ${node_name} + build_path: ./build/${node_name} + on_boot: + - lambda: |- + id(my_ota).set_auth_password("${new_ota_password}"); + +logger: + +time: + - platform: homeassistant + id: hass_time + timezone: 'Australia/Melbourne' + - platform: sntp + id: net_time + timezone: 'Australia/Melbourne' + +api: + # password: !secret api_password + +ota: + id: my_ota + password: !secret ota_password + +<<: !include wifi.yaml + +text_sensor: + - platform: version + name: ${friendly_name} ESPHome Version + disabled_by_default: true + hide_timestamp: true + + - platform: wifi_info + ip_address: + name: ${friendly_name} IP Address + disabled_by_default: true + ssid: + name: ${friendly_name} SSID + disabled_by_default: true + bssid: + name: ${friendly_name} BSSID + disabled_by_default: true + mac_address: + name: ${friendly_name} MAC Address + disabled_by_default: true + +sensor: + - platform: wifi_signal + name: "${friendly_name} WiFi Signal" + update_interval: 60s + +binary_sensor: + - platform: status + name: "${friendly_name} Status" + disabled_by_default: true + +button: + - platform: restart + id: restart_button + name: "${friendly_name} Restart" diff --git a/esphome/common/ble-gateway.yaml b/esphome/common/ble-gateway.yaml new file mode 100644 index 0000000..2bdd99e --- /dev/null +++ b/esphome/common/ble-gateway.yaml @@ -0,0 +1,26 @@ +external_components: + # - source: github://myhomeiot/esphome-components # ble_gateway + - source: github://ilarrain/esphome-components # ble_gateway fork with discovery option + +esp32_ble_tracker: + scan_parameters: + active: false + +ble_gateway: + id: blegateway + discovery: true + on_ble_advertise: + then: + homeassistant.event: + event: esphome.on_ble_advertise + data: + packet: !lambda return packet; + +text_sensor: + - platform: homeassistant + id: ble_gateway_devices + entity_id: binary_sensor.ble_gateway + attribute: devices + on_value: + then: + lambda: id(blegateway).set_devices(x); diff --git a/esphome/common/kogan-power-strip.yaml b/esphome/common/kogan-power-strip.yaml new file mode 100644 index 0000000..cd51a55 --- /dev/null +++ b/esphome/common/kogan-power-strip.yaml @@ -0,0 +1,105 @@ +# https://www.esphome-devices.com/devices/Kogan-Smarterhome-Smart-Power-Board-With-Usb-Ports-Energy-Meter/ +substitutions: + plug_icon: mdi:power-socket-au + usb_icon: mdi:usb-port + plug1_restore: RESTORE_DEFAULT_ON + plug2_restore: RESTORE_DEFAULT_ON + plug3_restore: RESTORE_DEFAULT_ON + usb_restore: ALWAYS_ON + + # Higher value gives lower watt readout + current_res: "0.00250" + # Lower value gives lower voltage readout + voltage_div: "799" + +esp8266: + board: esp8285 + restore_from_flash: true + +binary_sensor: + - platform: gpio + pin: + number: GPIO0 + mode: INPUT_PULLUP + inverted: true + name: "${friendly_name}_button" + on_press: + - switch.toggle: relay3 + + - platform: status + name: "${friendly_name}_status" + +switch: + - platform: gpio + id: green_led + pin: + number: GPIO1 + inverted: true + restore_mode: ALWAYS_OFF + + - platform: gpio + name: "${friendly_name} Plug 1" + pin: GPIO13 + id: relay1 + icon: ${plug_icon} + restore_mode: ${plug1_restore} + + - platform: gpio + name: "${friendly_name} Plug 2" + pin: GPIO14 + id: relay2 + icon: ${plug_icon} + restore_mode: ${plug2_restore} + + - platform: gpio + name: "${friendly_name} Plug 3" + pin: GPIO3 + id: relay3 + icon: ${plug_icon} + restore_mode: ${plug3_restore} + on_turn_on: + - switch.turn_on: green_led + on_turn_off: + - switch.turn_off: green_led + + - platform: gpio + name: "${friendly_name} USB" + pin: GPIO15 + id: relayusb + icon: ${usb_icon} + restore_mode: ${usb_restore} + +sensor: + - platform: hlw8012 + sel_pin: + number: GPIO12 + inverted: true + cf_pin: GPIO04 + cf1_pin: GPIO05 + current: + id: current + name: "${friendly_name} Current" + unit_of_measurement: A + voltage: + id: voltage + name: "${friendly_name} Voltage" + unit_of_measurement: V + power: + id: wattage + name: "${friendly_name} Wattage" + unit_of_measurement: W + energy: + id: energy + name: "${friendly_name} Energy Usage" + unit_of_measurement: Wh + current_resistor: ${current_res} + voltage_divider: ${voltage_div} + change_mode_every: 1 # default 8 + update_interval: 5s + + - platform: total_daily_energy + name: "${friendly_name} Total Daily Energy" + power_id: wattage + filters: + - multiply: 0.001 + unit_of_measurement: kWh diff --git a/esphome/common/wifi.yaml b/esphome/common/wifi.yaml new file mode 100644 index 0000000..138541c --- /dev/null +++ b/esphome/common/wifi.yaml @@ -0,0 +1,12 @@ +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + # domain: !secret wifi_domain + fast_connect: true + #power_save_mode: none + ap: + ssid: ${node_name} + +captive_portal: +#web_server: +# port: 80 diff --git a/esphome/front-gate.yaml b/esphome/front-gate.yaml new file mode 100644 index 0000000..7f012bc --- /dev/null +++ b/esphome/front-gate.yaml @@ -0,0 +1,134 @@ +substitutions: + node_name: "front-gate" + friendly_name: "Front Gate" + +esphome: + platform: ESP8266 + board: esp8285 + +packages: + base: !include common/base.yaml + +logger: + level: DEBUG + +web_server: + version: 2 + include_internal: true + +binary_sensor: + - platform: gpio + name: "${friendly_name} Contact" + disabled_by_default: true + device_class: garage_door + id: contact + pin: + number: GPIO4 + inverted: false + mode: INPUT_PULLUP + filters: + # Takes advantage of the fact that gate movement causes this GPIO pin to + # flicker (probably due to wire moving). We can use that initial change + # in state as a signal to set the cover operation. Later, when the final + # value settles (after debounces) we can set it back to idle. + - lambda: |- + if(id(gate).current_operation == CoverOperation::COVER_OPERATION_IDLE) { + id(gate).current_operation = (x ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING); + id(gate).publish_state(); + } + return x; + + # during gate movement, the wire movement seems to cause the state to rapidly flicker + - delayed_on_off: 5000ms + + - lambda: |- + id(gate).current_operation = COVER_OPERATION_IDLE; + id(gate).publish_state(); + return x; + + on_state: + then: + - cover.template.publish: + id: gate + current_operation: IDLE + + - platform: gpio + pin: + number: GPIO14 + mode: INPUT_PULLUP + inverted: true + name: "${friendly_name} Button" + disabled_by_default: true + on_multi_click: + - timing: + - ON for at most 1s + - OFF for at least 0.2s + then: + switch.turn_on: relay + - timing: + - ON for at least 4s + then: + button.press: restart_button # in common/base.yaml + +button: + - platform: template + name: "${friendly_name} Button" + on_press: + then: + - if: + condition: + - switch.is_off: relay + then: + - switch.turn_on: relay + +switch: + - platform: gpio + pin: GPIO5 + name: "${friendly_name} Relay" + id: relay + disabled_by_default: true + on_turn_on: + - light.turn_on: wifi_led + - delay: 1s + - switch.turn_off: relay + - light.turn_off: wifi_led + +light: + - platform: status_led + name: "${friendly_name} WiFi LED" + id: wifi_led + disabled_by_default: true + pin: GPIO12 + +cover: + - platform: template + id: gate + device_class: garage + name: "${friendly_name}" + lambda: "return id(contact).state ? COVER_CLOSED : COVER_OPEN;" + open_action: + - if: + condition: + and: + - switch.is_off: relay + - binary_sensor.is_on: contact # GATE IS CLOSED + - lambda: return id(gate).current_operation == COVER_OPERATION_IDLE; # GATE IS IDLE + then: + - switch.turn_on: relay + stop_action: + - if: + condition: + and: + - binary_sensor.is_on: contact + - lambda: return id(gate).current_operation != COVER_OPERATION_IDLE; # GATE IS ACTIVE + then: + - switch.turn_on: relay + close_action: + - if: + condition: + and: + - switch.is_off: relay + - binary_sensor.is_off: contact # GATE NOT CLOSED + - lambda: return id(gate).current_operation == COVER_OPERATION_IDLE; # GATE IS IDLE + then: + - switch.turn_on: relay diff --git a/esphome/power-strip-1686ec.yaml b/esphome/power-strip-1686ec.yaml new file mode 100644 index 0000000..4760dc6 --- /dev/null +++ b/esphome/power-strip-1686ec.yaml @@ -0,0 +1,17 @@ +substitutions: + node_name: power-strip-1686ec + friendly_name: Power Strip 1686ec + + plug1_restore: RESTORE_DEFAULT_ON + plug2_restore: RESTORE_DEFAULT_ON + plug3_restore: RESTORE_DEFAULT_ON + usb_restore: ALWAYS_ON + + # Higher value gives lower watt readout + current_res: "0.00250" + # Lower value gives lower voltage readout + voltage_div: "799" + +packages: + base: !include common/base.yaml + strip: !include common/kogan-power-strip.yaml diff --git a/esphome/power-strip-1687f5.yaml b/esphome/power-strip-1687f5.yaml new file mode 100644 index 0000000..90bc232 --- /dev/null +++ b/esphome/power-strip-1687f5.yaml @@ -0,0 +1,17 @@ +substitutions: + node_name: power-strip-1687f5 + friendly_name: 'Power Strip (16:86:F5)' + + plug1_restore: RESTORE_DEFAULT_ON + plug2_restore: RESTORE_DEFAULT_ON + plug3_restore: RESTORE_DEFAULT_ON + usb_restore: ALWAYS_ON + + # Higher value gives lower watt readout + current_res: "0.00250" + # Lower value gives lower voltage readout + voltage_div: "799" + +packages: + base: !include common/base.yaml + strip: !include common/kogan-power-strip.yaml diff --git a/lovelace/lovelace.3d_printing.yaml b/lovelace/lovelace.3d_printing.yaml new file mode 100644 index 0000000..deb6d8b --- /dev/null +++ b/lovelace/lovelace.3d_printing.yaml @@ -0,0 +1,162 @@ +config: + title: 3D Printing + views: + - badges: [] + cards: + - aspect_ratio: '4:3' + camera_image: camera.3d_printer + camera_view: live + entity: camera.3d_printer + show_name: false + show_state: false + type: picture-entity + view_layout: + position: sidebar + - entities: + - entity: switch.3d_printer_plug + name: 3D Printer Power + - conditions: + - entity: switch.3d_printer_plug + state: 'on' + row: + entity: switch.3d_printer_connection + type: conditional + - conditions: + - entity: switch.3d_printer_plug + state: 'on' + - entity: sensor.octoprint_current_state + state_not: unavailable + - entity: sensor.octoprint_current_state + state_not: Operational + row: + entity: button.octoprint_stop_job + type: conditional + - conditions: + - entity: switch.3d_printer_plug + state: 'on' + - entity: binary_sensor.octoprint_printing + state: 'on' + - entity: sensor.octoprint_current_state + state: Printing + row: + entity: button.octoprint_pause_job + type: conditional + - conditions: + - entity: switch.3d_printer_plug + state: 'on' + - entity: binary_sensor.octoprint_printing + state: 'off' + - entity: sensor.octoprint_current_state + state_not: Printing + - entity: sensor.octoprint_current_state + state_not: Operational + - entity: sensor.octoprint_current_state + state_not: unknown + row: + entity: button.octoprint_resume_job + type: conditional + - entity: sensor.octoprint_current_state + name: Current status + secondary_info: + entity: binary_sensor.octoprint_printing + name: Printing + type: custom:multiple-entity-row + - conditions: + - entity: switch.3d_printer_plug + state: 'on' + - entity: sensor.octoprint_current_state + state_not: unavailable + - entity: sensor.octoprint_current_state + state_not: Operational + row: + entities: + - entity: sensor.octoprint_estimated_finish_time + format: total + hide_unavailable: true + name: ETA + entity: sensor.octoprint_job_percentage + name: Progress + secondary_info: + entity: sensor.octoprint_start_time + format: relative + hide_unavailable: true + name: started + state_header: completion + type: custom:multiple-entity-row + type: conditional + - conditions: + - entity: switch.3d_printer_plug + state: 'on' + - entity: sensor.octoprint_current_state + state_not: unavailable + row: + entities: + - entity: sensor.octoprint_target_bed_temp + name: target + entity: sensor.octoprint_actual_bed_temp + name: Bed temperature + secondary_info: last-changed + state_header: actual + type: custom:multiple-entity-row + type: conditional + - conditions: + - entity: switch.3d_printer_plug + state: 'on' + - entity: sensor.octoprint_current_state + state_not: unavailable + row: + entities: + - entity: sensor.octoprint_target_tool0_temp + name: target + entity: sensor.octoprint_target_tool0_temp + name: Nozzle temperature + secondary_info: last-changed + state_header: actual + type: custom:multiple-entity-row + type: conditional + - conditions: + - entity: binary_sensor.octoprint_printing_error + state: 'on' + row: + entity: binary_sensor.octoprint_printing_error + type: conditional + type: entities + view_layout: + position: sidebar + - entities: + - sensor.3d_printer_plug_wattage + - sensor.3d_printer_plug_total_daily_energy + footer: + detail: 2 + entity: sensor.3d_printer_plug_wattage + hours_to_show: 6 + type: graph + type: entities + view_layout: + position: sidebar + - card: + aspect_ratio: 50% + type: iframe + url: https://10.10.20.42/?fullscreen=1#tab_plugin_prettygcode + conditions: + - entity: binary_sensor.octoprint_printing + state: 'on' + type: conditional + - entities: + - entity: sensor.octoprint_actual_bed_temp + name: Actual bed temp + - entity: sensor.octoprint_target_bed_temp + name: Target bed temp + - entity: sensor.octoprint_actual_tool0_temp + name: Actual nozzle temp + - entity: sensor.octoprint_target_tool0_temp + name: Target nozzle temp + hours_to_show: 2 + type: history-graph + view_layout: + position: sidebar + icon: mdi:printer-3d + path: 0 + theme: Backend-selected + title: 3D Printer + type: sidebar diff --git a/lovelace/lovelace.bos_office.yaml b/lovelace/lovelace.bos_office.yaml new file mode 100644 index 0000000..54fc218 --- /dev/null +++ b/lovelace/lovelace.bos_office.yaml @@ -0,0 +1,45 @@ +config: + views: + - badges: [] + cards: + - chips: + - entity: light.bos_office + type: light + use_light_color: true + - entity: binary_sensor.bo_s_office_door_contact + type: entity + use_entity_picture: false + - entity: binary_sensor.bo_s_office_is_occupied + icon: mdi:motion-sensor + type: entity + - entity: sensor.ble_temperature_bos_office_a4c1380f0b98 + type: entity + - entity: sensor.ble_humidity_bos_office_a4c1380f0b98 + type: entity + - entity: sensor.bo_s_desk_plug_power + name: Desk + type: entity + - entity: sensor.bo_s_office_plug_power + type: entity + - entity: sensor.bo_s_office_perception + type: entity + type: custom:mushroom-chips-card + - card: + type: entities + filter: + exclude: + - state: unknown + - state: unavailable + include: + - area: Bo's Office + options: + secondary_info: last-changed + show_empty: false + sort: + method: domain + reverse: true + type: custom:auto-entities + icon: mdi:chair-rolling + theme: Backend-selected + title: Bo's Office + type: custom:grid-layout diff --git a/lovelace/lovelace.lovelace_gardens.yaml b/lovelace/lovelace.lovelace_gardens.yaml new file mode 100644 index 0000000..bbdba21 --- /dev/null +++ b/lovelace/lovelace.lovelace_gardens.yaml @@ -0,0 +1,623 @@ +config: + views: + - badges: [] + cards: + - card: + type: entities + filter: + exclude: + - entity_id: /tent/ + - state: unavailable + - area: Garden Shed + - entity_id: /human_readable/ + include: + - name: /[gG]arden/ + - name: /[tT]ent/ + type: custom:auto-entities + - card: + type: history-graph + filter: + exclude: + - name: /[bB]attery/ + - state: scening + - entity_id: /tent/ + - state: unavailable + - area: Garden Shed + - entity_id: /human_readable/ + include: + - name: /[gG]arden/ + - name: /[tT]ent/ + - entity_id: sensor.home_weather_temperature + - entity_id: sensor.home_weather_forecast_temperature + type: custom:auto-entities + icon: mdi:flower + path: garden + title: Garden + - badges: + - entity: sensor.tent_temperature_cached + name: Temp + - entity: sensor.tent_humidity_cached + name: Humidity + - entity: sensor.tent_vpd + name: VPD + - entity: sensor.tent_reservoir_ph + name: pH + - entity: sensor.tent_reservoir_ec_us + name: EC + cards: + - card: + camera_image: camera.tent_camera_mjpeg + camera_view: live + entities: + - entity: switch.tent_cam_focus + show_state: true + - entity: switch.tent_cam_night_vision + show_state: true + - entity: sensor.tent_cam_battery_level + show_state: true + - entity: sensor.tent_cam_battery_temperature + show_state: true + - entity: sensor.tent_cam_light_level + show_state: true + type: picture-glance + view_layout: + position: sidebar + conditions: + - entity: binary_sensor.tent_lights_status + state: 'on' + type: conditional + - camera_image: camera.tent_timelapse + camera_view: live + entity: camera.tent_timelapse + name: Timelapse + show_name: true + show_state: false + type: picture-entity + view_layout: + position: sidebar + - entities: + - entities: + - entity: switch.tent_lights_local + icon: mdi:wall-sconce-flat + name: false + state_color: true + tap_action: + action: toggle + - entity: switch.tent_fans_local + icon: mdi:fan + name: false + state_color: true + tap_action: + action: toggle + - entity: switch.tent_humidifier_local + icon: mdi:air-humidifier + name: false + state_color: true + tap_action: + action: toggle + - entity: switch.tent_misc_local + icon: mdi:power-socket-au + name: false + state_color: true + tap_action: + action: toggle + - entity: switch.tent_usb_local + icon: mdi:usb-port + name: false + state_color: true + tap_action: + action: toggle + entity: switch.tent_power_plug + name: Power + secondary_info: + entity: sensor.tent_wattage + name: false + show_state: false + state_color: true + toggle: true + type: custom:multiple-entity-row + footer: + entity: sensor.tent_wattage + hours_to_show: 24 + type: graph + show_header_toggle: false + state_color: true + type: entities + view_layout: + position: sidebar + - entities: + - entities: + - entity: sensor.tent_humidity + format: precision1 + name: Humidity + entity: sensor.tent_temperature + format: precision1 + icon: mdi:tent + name: Tent + state_header: Temperature + type: custom:multiple-entity-row + - entities: + - entity: sensor.tent_reservoir_ec_us + format: kilo + name: EC + unit: false + - entity: sensor.tent_reservoir_ph + name: pH + unit: false + entity: sensor.tent_reservoir_temperature + format: precision1 + icon: mdi:cup-water + name: Reservoir + state_header: Temperature + type: custom:multiple-entity-row + show_header_toggle: false + state_color: false + type: entities + view_layout: + position: sidebar + - card: + entities: + - entity: input_select.tent_stage + - entities: + - hide_if_template: '{% set v = states(''sensor.tent_reservoir_ph'') %} + {% set min = states(''input_number.minimum_ph'') %} {% set max = states(''input_number.maximum_ph'') + %} {{ iif(v < max and v > min, v, -1 * v) }}' + icon: mdi:alert-decagram + styles: + --paper-item-icon-color: red + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.minimum_ph + - entity: input_number.minimum_ph + name: min + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.minimum_ph + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.maximum_ph + - entity: input_number.maximum_ph + name: max + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.maximum_ph + entity: sensor.tent_reservoir_ph + name: pH + secondary_info: + entity: sensor.tent_reservoir_ph + name: false + unit: false + show_state: false + type: custom:multiple-entity-row + - entities: + - hide_if_template: '{% set v = states(''sensor.tent_vpd'') %} {% set min + = states(''input_number.minimum_tent_vpd'') %} {% set max = states(''input_number.maximum_tent_vpd'') + %} {{ iif(v < max and v > min, v, -1 * v) }}' + icon: mdi:alert-decagram + styles: + --paper-item-icon-color: red + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.minimum_tent_vpd + - entity: input_number.minimum_tent_vpd + name: min + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.minimum_tent_vpd + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.maximum_tent_vpd + - entity: input_number.maximum_tent_vpd + name: max + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.maximum_tent_vpd + entity: sensor.tent_vpd + name: VPD + secondary_info: + entity: sensor.tent_vpd + name: false + show_state: false + type: custom:multiple-entity-row + - entities: + - hide_if_template: '{% set v = states(''sensor.tent_humidity'') %} {% set + min = states(''input_number.minimum_tent_humidity'') %} {% set max = + states(''input_number.maximum_tent_humidity'') %} {{ iif(v < max and + v > min, v, -1 * v) }}' + icon: mdi:alert-decagram + styles: + --paper-item-icon-color: red + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.minimum_tent_humidity + - entity: input_number.minimum_tent_humidity + format: precision0 + name: min + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.minimum_tent_humidity + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.maximum_tent_humidity + - entity: input_number.maximum_tent_humidity + format: precision0 + name: max + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.maximum_tent_humidity + entity: sensor.tent_humidity + name: Humidity + secondary_info: + entity: sensor.tent_humidity + name: false + show_state: false + type: custom:multiple-entity-row + - entities: + - hide_if_template: '{% set v = states(''sensor.tent_temperature'') %} {% + set min = states(''input_number.minimum_tent_temperature'') %} {% set + max = states(''input_number.maximum_tent_temperature'') %} {{ iif(v + < max and v > min, v, -1 * v) }}' + icon: mdi:alert-decagram + styles: + --paper-item-icon-color: red + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.tent_temperature + - entity: input_number.minimum_tent_temperature + format: precision0 + name: min + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.minimum_tent_temperature + - icon: mdi:chevron-down + styles: + margin: 0 + tap_action: + action: call-service + service: input_number.decrement + service_data: + entity_id: input_number.maximum_tent_temperature + - entity: input_number.maximum_tent_temperature + format: precision0 + name: max + styles: + margin: 0 + unit: false + - icon: mdi:chevron-up + tap_action: + action: call-service + service: input_number.increment + service_data: + entity_id: input_number.maximum_tent_temperature + entity: sensor.tent_temperature + icon: mdi:temperature-celsius + name: Temperature + secondary_info: + entity: sensor.tent_temperature + name: false + show_state: false + type: custom:multiple-entity-row + - entities: + - entity: input_datetime.tent_day_start + name: start + - entity: input_datetime.tent_night_start + name: end + entity: input_datetime.tent_day_start + icon: mdi:sun-wireless + name: Day Cycle + show_state: false + type: custom:multiple-entity-row + type: entities + entities: + - sensor.tent_reservoir_ph + - sensor.tent_vpd + - sensor.tent_humidity + - sensor.tent_temperature + - input_number.minimum_ph + - input_number.maximum_ph + - input_number.minimum_tent_vpd + - input_number.maximum_tent_vpd + - input_number.minimum_tent_temperature + - input_number.maximum_tent_temperature + - input_number.minimum_tent_humidity + - input_number.maximum_tent_humidity + type: custom:card-templater + view_layout: + position: sidebar + - cards: + - days_to_show: 3 + entities: + - entity: sensor.bendigo_temp + - entity: sensor.home_weather_temperature + name: Weather + - entity: sensor.tent_temperature + name: Tent + title: Air Temperatures + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.bendigo_humidity + - entity: sensor.home_weather_humidity + name: Weather + - entity: sensor.tent_humidity + name: Tent + title: Humidity + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_vpd + name: VPD + title: Vapor Pressure Deficit + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_reservoir_temperature + name: "\xB0C" + refresh_interval: 120 + title: Reservoir Temperature + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_reservoir_ec_us + name: EC + refresh_interval: 120 + title: Reservoir EC + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_reservoir_ph + name: pH + refresh_interval: 120 + title: Reservoir pH + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_hhcc_1_illuminance + name: A + - entity: sensor.tent_hhcc_2_illuminance + name: B + stat_types: + - max + title: Illuminance + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_hhcc_1_moisture + name: A + - entity: sensor.tent_hhcc_2_moisture + name: B + title: Soil Moisture + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_hhcc_1_temperature + name: A + - entity: sensor.tent_hhcc_2_temperature + name: B + title: Soil Temperatures + type: statistics-graph + - days_to_show: 3 + entities: + - entity: sensor.tent_hhcc_1_soil_conductivity + name: A + - entity: sensor.tent_hhcc_2_soil_conductivity + name: B + title: Soil EC + type: statistics-graph + layout: + max_cols: 3 + layout_type: custom:horizontal-layout + square: false + type: custom:layout-card + - card: + title: Automations + type: entities + filter: + exclude: + - name: /Snapshot|Restore/ + - entity_id: /night_mode/ + include: + - entity_id: script.refill_tent_humidifier + options: + entities: + - hide_if: 'on' + icon: mdi:play + tap_action: + action: call-service + service: this.entity_id + - hide_if: 'off' + icon: mdi:stop + tap_action: + action: call-service + service: script.turn_off + service_data: + entity_id: this.entity_id + - attribute: remaining + entity: timer.humidifier_time_till_refill + format: relative + name: remaining + secondary_info: + entity: input_datetime.tent_humidifier_refilled_at + format: relative + name: Refilled + show_state: false + type: custom:multiple-entity-row + sort: + method: last_triggered + reverse: true + - domain: script + or: + - entity_id: /tent/ + - area: Garden Shed + sort: + entities: + - hide_if: 'on' + icon: mdi:play + tap_action: + action: call-service + service: this.entity_id + - hide_if: 'off' + icon: mdi:stop + tap_action: + action: call-service + service: script.turn_off + service_data: + entity_id: this.entity_id + method: last_triggered + reverse: true + - domain: automation + entity_id: /tent/ + options: + entities: + - icon: mdi:play + tap_action: + action: call-service + service: automation.trigger + service_data: + entity_id: this.entity_id + secondary_info: last-triggered + state_color: true + toggle: true + type: custom:multiple-entity-row + sort: + method: last_triggered + reverse: true + sort: + method: domain + numeric: false + reverse: true + type: custom:auto-entities + unique: true + view_layout: + position: sidebar + - entities: + - entity: button.garden_shed_ble_relay_restart + name: Restart + - entity: binary_sensor.garden_shed_ble_relay_status + name: Status + secondary_info: last-changed + - entity: sensor.garden_shed_ble_relay_wifi_signal + name: Wi-fi Signal + - entity: sensor.garden_shed_ble_relay_uptime_human_readable + name: Uptime + title: Sensor Proxy + type: entities + view_layout: + position: sidebar + icon: mdi:tent + title: Tent + type: sidebar + visible: + - user: a85f738edac2433eaba57bcd13669897 + - badges: [] + cards: + - entities: + - entity: sensor.ble_humidity_cure_jar_1_a4c138453702 + - entity: sensor.ble_humidity_cure_jar_2_a4c138985d30 + - entity: sensor.ble_humidity_cure_jar_3_a4c138ab2ffc + - entity: sensor.ble_humidity_stash_jar_a4c1382baf8a + line_width: 3 + min_bound_range: 10 + name: Humidities + points_per_hour: 2 + show: + fill: fade + points: hover + state: last + type: custom:mini-graph-card + - entities: + - entity: sensor.ble_temperature_cure_jar_1_a4c138453702 + - entity: sensor.ble_temperature_cure_jar_2_a4c138985d30 + - entity: sensor.ble_temperature_cure_jar_3_a4c138ab2ffc + - entity: sensor.ble_temperature_stash_jar_a4c1382baf8a + line_width: 3 + min_bound_range: 10 + name: Temperatures + points_per_hour: 2 + show: + fill: fade + points: false + type: custom:mini-graph-card + icon: mdi:bucket-outline + path: cure + theme: Backend-selected + title: Cure + visible: + - user: a85f738edac2433eaba57bcd13669897 diff --git a/lovelace/lovelace.lovelace_sensors.yaml b/lovelace/lovelace.lovelace_sensors.yaml new file mode 100644 index 0000000..1e7e5d2 --- /dev/null +++ b/lovelace/lovelace.lovelace_sensors.yaml @@ -0,0 +1,336 @@ +config: + views: + - badges: [] + cards: + - card: + title: Bo's Office + type: entities + filter: + exclude: + - state: unavailable + include: + - area: bo_s_office + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Ri's Office + type: entities + filter: + exclude: + - state: unavailable + include: + - area: ri_s_office + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Bedroom + type: entities + filter: + exclude: + - state: unavailable + include: + - area: bedroom + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Spare Room + type: entities + filter: + exclude: + - state: unavailable + include: + - area: spare_room + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Living Room + type: entities + filter: + exclude: + - state: unavailable + include: + - area: living_room + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Analog Room + type: entities + filter: + exclude: + - state: unavailable + include: + - area: analog_room + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Bathroom + type: entities + filter: + exclude: + - state: unavailable + include: + - area: bathroom + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Kitchen + type: entities + filter: + exclude: + - state: unavailable + include: + - area: kitchen + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Laundry + type: entities + filter: + exclude: + - state: unavailable + include: + - area: laundry + sort: + method: domain + reverse: true + type: custom:auto-entities + - card: + title: Outdoors + type: entities + filter: + exclude: + - state: unavailable + include: + - area: outdoors + sort: + method: domain + reverse: true + type: custom:auto-entities + icon: '' + path: by-room + theme: Backend-selected + title: By room + - badges: [] + cards: + - card: + state_color: false + title: Humidity + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: humidity + state_class: measurement + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Temperature + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: temperature + state_class: measurement + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Battery + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: battery + state_class: measurement + integration: /ble/ + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Power + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: power + state_class: measurement + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Current + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: current + state_class: measurement + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Voltage + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: voltage + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Pressure + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: pressure + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Illuminance + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: illuminance + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Signal Strength + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: signal_strength + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: Ozone + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: ozone + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + - card: + state_color: false + title: PM2.5 + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: pm25 + options: + secondary_info: last-updated + show_empty: false + sort: + method: last_changed + reverse: true + type: custom:auto-entities + theme: Backend-selected + title: Recently changed diff --git a/lovelace/lovelace.lovelace_servers.yaml b/lovelace/lovelace.lovelace_servers.yaml new file mode 100644 index 0000000..d6eeddd --- /dev/null +++ b/lovelace/lovelace.lovelace_servers.yaml @@ -0,0 +1,326 @@ +config: + title: Servers + views: + - badges: + - entity: sensor.plex_tumtum_tree + name: Tumtum + - entity: media_player.apple_tv + name: "\uF8FF TV" + - entity: media_player.plex_plex_for_apple_tv_living_room + name: Plex + cards: + - entities: + - entity: sensor.nas_cpu_utilization_total + - entity: sensor.nas_memory_usage_real + - entity: sensor.nas_volume_1_volume_used + hours_to_show: 24 + refresh_interval: 0 + type: history-graph + - entities: + - entity: sensor.rtorrent_down_speed + - entity: sensor.rtorrent_up_speed + - entity: sensor.nzbget_speed_kilobytes_per_sec + - entity: sensor.rtorrent_downloading_torrents + - entity: sensor.rtorrent_uploading_torrents + hours_to_show: 6 + refresh_interval: 5 + type: history-graph + - cards: + - entity: sensor.plex_tumtum_tree + name: Plex + type: entity + - card: + type: entities + filter: + exclude: + - state: unavailable + - state: 'off' + - state: idle + - state: ok + - state: problem + include: + - domain: media_player + entity_id: /plex/ + sort: + method: friendly_name + type: custom:auto-entities + type: vertical-stack + - entities: + - entity: sensor.plex_tumtum_tree + - entity: sensor.sonarr_upcoming + - entity: sensor.sonarr_queue + - entity: sensor.nas_cpu_utilization_total + - entity: sensor.nas_cpu_load_averarge_5_min + - entity: sensor.nas_cpu_load_averarge_15_min + - entity: sensor.nas_memory_usage_real + - entity: sensor.nas_network_down + - entity: sensor.nas_network_up + - entity: sensor.nas_temperature + - entity: binary_sensor.nas_update_available + - entity: sensor.nas_volume_1_average_disk_temp + - entity: sensor.nas_volume_1_volume_used + - entity: sensor.rtorrent_all_torrents + icon: hass:download + - entity: sensor.rtorrent_downloading_torrents + icon: hass:download + - entity: sensor.rtorrent_uploading_torrents + icon: hass:upload + - entity: sensor.rtorrent_active_torrents + type: entities + - entities: + - entity: sensor.nzbget_speed_kilobytes_per_sec + - entity: sensor.rtorrent_down_speed + - entity: sensor.rtorrent_up_speed + - entity: sensor.rtorrent_active_torrents + - entity: sensor.rtorrent_downloading_torrents + - entity: sensor.rtorrent_uploading_torrents + type: entities + icon: hass:plex + path: media + title: Media + - badges: + - entity: sensor.nas_volume_1_status + - entity: update.nas_dsm_update + - entity: sensor.nas_cpu_utilization_total + - entity: sensor.nas_volume_1_volume_used + - entity: sensor.nas_memory_usage_real + - entity: sensor.nas_ups_battery_charge + cards: + - card: + type: entities + filter: + exclude: + - device: NAS + - name: /NAS UPS/ + - entity_id: /nas_drive_\d/ + - entity_id: /nas_cache_device_/ + - entity_id: /device_tracker/ + - state: unavailable + include: + - name: /NAS/ + type: custom:auto-entities + - card: + type: entities + filter: + exclude: + - attributes: + device_class: safety + state: 'off' + - attributes: + device_class: update + state: 'off' + - state: normal + include: + - device: NAS + type: custom:auto-entities + - card: + title: Noteworthy + type: entities + filter: + exclude: + - attributes: + device_class: safety + state: 'off' + - attributes: + device_class: update + state: 'off' + - state: normal + - state: not_use + - entity_id: /temp/ + state: < 45 + include: + - entity_id: /nas_drive/ + - entity_id: /nas_cache/ + show_empty: false + sort: + method: entity_id + numeric: true + type: custom:auto-entities + - entities: + - entity: sensor.nas_network_down + - entity: sensor.nas_network_up + hours_to_show: 24 + refresh_interval: 0 + type: history-graph + - entities: + - entity: sensor.nas_memory_size + - entity: sensor.nas_memory_total_real + hours_to_show: 24 + refresh_interval: 0 + type: history-graph + - card: + type: history-graph + filter: + exclude: + - entity_id: /status_data/ + - entity_id: /nominal/ + - entity_id: /transfer/ + include: + - entity_id: /nas_ups/ + type: custom:auto-entities + - card: + type: history-graph + filter: + exclude: [] + include: + - entity_id: /nas_.*temp/ + type: custom:auto-entities + - card: + type: history-graph + filter: + exclude: [] + include: + - entity_id: /_(rx|tx)$/ + integration: unifi + type: custom:auto-entities + icon: mdi:nas + path: nas + theme: Backend-selected + title: NAS + - badges: [] + cards: + - entities: + - sensor.load_1m + - sensor.load_5m + - sensor.load_15m + - sensor.memory_use_percent + - sensor.processor_use + - sensor.disk_use_percent_config + - sensor.home_assistant_v2_db + title: HASS + type: history-graph + - entities: + - sensor.aircast_cpu_percent + - sensor.deconz_cpu_percent + - sensor.esphome_cpu_percent + - sensor.file_editor_cpu_percent + - sensor.frigate_nvr_full_access_cpu_percent + - sensor.glances_cpu_percent + - sensor.home_assistant_google_drive_backup_cpu_percent + - sensor.influxdb_cpu_percent + - sensor.mosquitto_broker_cpu_percent + - sensor.node_red_cpu_percent + - sensor.samba_share_cpu_percent + - sensor.sqlite_web_cpu_percent + - sensor.terminal_ssh_cpu_percent + - sensor.vaultwarden_bitwarden_cpu_percent + - sensor.zerotier_one_cpu_percent + hours_to_show: 24 + title: CPU + type: history-graph + - entities: + - sensor.zerotier_one_memory_percent + - sensor.vaultwarden_bitwarden_memory_percent + - sensor.terminal_ssh_memory_percent + - sensor.sqlite_web_memory_percent + - sensor.samba_share_memory_percent + - sensor.node_red_memory_percent + - sensor.mosquitto_broker_memory_percent + - sensor.influxdb_memory_percent + - sensor.home_assistant_google_drive_backup_memory_percent + - sensor.glances_memory_percent + - sensor.frigate_nvr_full_access_memory_percent + - sensor.file_editor_memory_percent + - sensor.esphome_memory_percent + - sensor.deconz_memory_percent + - sensor.aircast_memory_percent + hours_to_show: 24 + title: Memory + type: history-graph + icon: mdi:home-assistant + path: hass + theme: Backend-selected + title: HASS + - badges: [] + cards: + - all_series_config: + extend_to_end: false + group_by: + duration: 30min + func: raw + show: + extremas: true + stroke_width: 3 + apex_config: + chart: + toolbar: + show: true + tools: + pan: true + reset: true + zoom: true + zoomin: true + zoomout: true + zoom: + enabled: true + legend: + showForSingleSeries: true + plotOptions: + bar: + columnWidth: 50% + responsive: + - breakpoint: 765 + options: + chart: + height: 500px + - breakpoint: 1025 + options: + chart: + height: 400px + - breakpoint: 10000 + options: + chart: + height: auto + stroke: + curve: smooth + yaxis_precision: 0 + brush: + selection_span: 10m + experimental: + brush: true + graph_span: 48h + header: + show: true + title: Internet speed + now: + show: true + series: + - entity: sensor.speedtest_download + name: Download + type: line + unit: Mbps + yaxis_id: speed + - entity: sensor.speedtest_upload + name: Upload + type: line + unit: Mbps + yaxis_id: speed + - entity: sensor.speedtest_ping + group_by: + duration: 30min + func: max + name: Ping + stroke_width: 2 + type: column + unit: ms + yaxis_id: latency + type: custom:apexcharts-card + yaxis: + - id: speed + max: ~50 + min: ~0 + - id: latency + max: ~50 + min: ~0 + opposite: true + - card: + type: entities + filter: + exclude: [] + include: + - device: Laser Printer + type: custom:auto-entities + icon: '' + panel: false + path: misc + title: misc diff --git a/lovelace/lovelace.lovelace_shed.yaml b/lovelace/lovelace.lovelace_shed.yaml new file mode 100644 index 0000000..7270d20 --- /dev/null +++ b/lovelace/lovelace.lovelace_shed.yaml @@ -0,0 +1,3 @@ +config: + title: Outdoors + views: [] diff --git a/lovelace/lovelace.yaml b/lovelace/lovelace.yaml new file mode 100644 index 0000000..3ae8217 --- /dev/null +++ b/lovelace/lovelace.yaml @@ -0,0 +1,712 @@ +config: + title: Home + views: + - badges: [] + cards: + - cards: + - cards: + - entity: person.bo_jeanes + fill_container: false + hide_name: false + hide_state: false + type: custom:mushroom-person-card + use_entity_picture: true + - double_tap_action: + action: none + entity: sensor.template_room_bo_phone + icon: "{% if is_state(entity, 'not_home') and is_state('person.bo_jeanes',\ + \ 'home') %}\n mdi:cellphone-off\n{% else %}\n mdi:cellphone-marker\n\ + {% endif %}" + secondary: "{% if is_state('person.bo_jeanes', 'not_home') %}\n ~{{ states('proximity.bo_home')\ + \ }}m from home\n{% elif is_state(entity, 'not_home') %}\n Unknown\n\ + {% else %}\n {{ states(entity) | replace(\"_s_\",\"'s \") | replace(\"\ + _\",\" \") | title }}\n ~{{ state_attr(entity, 'distance') }}m\n{% endif\ + \ %}" + tap_action: + action: more-info + type: custom:mushroom-template-card + type: vertical-stack + - cards: + - entity: person.ri_liu + fill_container: false + hide_name: false + hide_state: false + layout: horizontal + type: custom:mushroom-person-card + use_entity_picture: true + - double_tap_action: + action: none + entity: sensor.template_room_ri_phone + icon: "{% if is_state(entity, 'not_home') and is_state('person.ri_liu',\ + \ 'home') %}\n mdi:cellphone-off\n{% else %}\n mdi:cellphone-marker\n\ + {% endif %}" + secondary: "{% if is_state('person.ri_liu', 'not_home') %}\n ~{{ states('proximity.ri_home')\ + \ }}m from home\n{% elif is_state(entity, 'not_home') %}\n Unknown\n\ + {% else %}\n {{ states(entity) | replace(\"_s_\",\"'s \") | replace(\"\ + _\",\" \") | title }}\n ~{{ state_attr(entity, 'distance') }}m\n{% endif\ + \ %}" + tap_action: + action: more-info + type: custom:mushroom-template-card + type: vertical-stack + type: horizontal-stack + - card: + type: custom:mushroom-chips-card + card_param: chips + filter: + exclude: [] + include: + - attributes: + device_class: door + domain: binary_sensor + options: + content: "{{ state_attr('this.entity_id', 'friendly_name') \n | replace('\ + \ contact','') \n | replace(' Door','') }}" + icon: "{% if is_state('this.entity_id', 'on') %}\n mdi:door-open\n{%\ + \ else %}\n mdi:door-closed\n{% endif %}" + tap_action: + action: more-info + type: template + use_light_color: true + state: 'on' + show_empty: false + type: custom:auto-entities + - card: + type: custom:mushroom-chips-card + card_param: chips + filter: + exclude: + - entity_id: /tent/ + - entity_id: '*double_lamp_*' + - area: Garden Shed + - name: /Purifier/ + include: + - domain: light + options: + content_info: name + type: light + use_light_color: true + sort: + method: name + sort: + method: friendly_name + type: custom:auto-entities + - entity: cover.front_gate + layout: horizontal + show_buttons_control: true + show_position_control: false + tap_action: + action: call-service + service: button.press + service_data: {} + target: + entity_id: button.front_gate_button + type: custom:mushroom-cover-card + - cards: + - card: + chips: + - chip: + content_template: Play default ({{ states('sensor.background_playlist') + }}) + icon: mdi:music + tap_action: + action: call-service + service: media_player.select_source + service_data: + source_template: '{{ states(''sensor.background_playlist'') }}' + target: + entity_id: media_player.denon_avr_x1600h_heos + type: template + conditions: + - entity: sensor.background_playlist + state_not: 'off' + type: conditional + - chip: + content: ABC Jazz - {{ states('sensor.abc_jazz_now_playing') }} + icon: mdi:music + tap_action: + action: call-service + service: media_player.select_source + service_data: + source: ABC Jazz (Jazz Music) + target: + entity_id: media_player.denon_avr_x1600h_heos + type: template + conditions: + - entity: sensor.current_living_room_media_player_source + state_not: ABC Jazz (Jazz Music) + type: conditional + - chip: + content: RRR - {{ states('sensor.rrr_now_playing') }} + icon: mdi:music + tap_action: + action: call-service + service: media_player.select_source + service_data: + source: Triple R 102.7 (Variety) + target: + entity_id: media_player.denon_avr_x1600h_heos + type: template + conditions: + - entity: sensor.current_living_room_media_player_source + state_not: Triple R 102.7 (Variety) + type: conditional + - chip: + content: PBS - {{ states('sensor.pbs_now_playing') }} + icon: mdi:music + tap_action: + action: call-service + service: media_player.select_source + service_data: + source: PBS 106.7FM Melbourne | (Variety) + target: + entity_id: media_player.denon_avr_x1600h_heos + type: template + conditions: + - entity: sensor.current_living_room_media_player_source + state_not: PBS 106.7FM Melbourne | (Variety) + type: conditional + - chip: + content: JJ - {{ states('sensor.jj_now_playing') }} + icon: mdi:music + tap_action: + action: call-service + service: media_player.select_source + service_data: + source: Double J (Indie Music) + target: + entity_id: media_player.denon_avr_x1600h_heos + type: template + conditions: + - entity: sensor.current_living_room_media_player_source + state_not: Double J (Indie Music) + type: conditional + - chip: + content: JJJ - {{ states('sensor.jjj_now_playing') }} + icon: mdi:music + tap_action: + action: call-service + service: media_player.select_source + service_data: + source: triple j 107.5 (Alternative Rock) + target: + entity_id: media_player.denon_avr_x1600h_heos + type: template + conditions: + - entity: sensor.current_living_room_media_player_source + state_not: triple j 107.5 (Alternative Rock) + type: conditional + type: custom:mushroom-chips-card + entities: + - sensor.background_playlist + type: custom:card-templater + - card: + type: vertical-stack + card_param: cards + filter: + exclude: + - state: unavailable + - state: 'off' + - state: idle + - state: standby + - entity_id: /spotify/ + - entity_id: /denon/ + - attributes: + source: HEOS Music + include: + - domain: media_player + not: + entity_id: '*.plex_*' + options: + media_controls: + - play_pause_stop + - on_off + - next + - previous + type: custom:mushroom-media-player-card + use_media_artwork: true + use_media_info: true + volume_controls: + - volume_set + - volume_buttons + - volume_mute + - attributes: + username: bjeanes + domain: media_player + entity_id: '*.plex_*' + options: + media_controls: + - play_pause_stop + - on_off + - next + - previous + type: custom:mushroom-media-player-card + use_media_artwork: true + use_media_info: true + volume_controls: + - volume_set + - volume_buttons + - volume_mute + show_empty: false + sort: + method: state + reverse: true + type: custom:auto-entities + type: horizontal-stack + - card: + state_color: true + title: Important + type: entities + filter: + exclude: + - state: unavailable + - state: unknown + include: + - attributes: + device_class: moisture + domain: binary_sensor + state: 'on' + - attributes: + device_class: problem + domain: binary_sensor + state: 'on' + - attributes: + device_class: connectivity + domain: binary_sensor + not: + entity_id: /robot_vacuum_(mop|water_box)/ + state: 'off' + - entity_id: calendar.on_call + state: 'on' + - entity_id: /fire_danger/ + not: + state: /Low|^High/ + - entity_id: /octoprint_printing/ + state: 'on' + - attributes: + state_class: measurement + unit_of_measurement: '%' + entity_id: /remaining/ + state: <10 + - attributes: + device_class: safety + state: 'on' + - entity_id: binary_sensor.electricity_price_spike + state: 'on' + - attributes: + days: <= 1 + device_class: garbage_collection__schedule + - attributes: + device_class: battery + not 1: + attributes: + Is Charging: true + not 2: + attributes: + battery_status: Charging + not 3: + attributes: + Is Charged: true + not 4: + attributes: + icon: /charging/ + options: + type: custom:battery-entity-row + state: < 10 + - attributes: + weeks_remaining: 0 + - entity_id: /cpu_percent/ + state: '> 70' + - entity_id: /memory_percent/ + state: '> 70' + - attributes: + device_class: update + state: 'on' + - domain: update + state: 'on' + - entity_id: sensor.recorder_age + state: '> 180' + show_empty: false + sort: + method: none + type: custom:auto-entities + unique: true + icon: hass:home + panel: false + path: default_view + title: Home + - badges: [] + cards: + - entities: + - entity: binary_sensor.in_bed + name: Anyone In bed + secondary_info: last-updated + - entity: input_boolean.bo_in_bed + - entity: input_boolean.ri_in_bed + type: entities + - aqi: + entity_id: sensor.bedroom_purifier_pm2_5 + unit: "\xB5g/m\xB3" + compact_view: true + entity: fan.bedroom_purifier + shortcuts: + - icon: mdi:weather-night + name: Silent + preset_mode: Silent + - icon: mdi:circle-slice-2 + name: 25% + percentage: 25 + - icon: mdi:circle-slice-4 + name: 50% + percentage: 50 + - icon: mdi:circle-slice-6 + name: 75% + percentage: 75 + - icon: mdi:circle-slice-8 + name: 100% + percentage: 100 + - icon: mdi:brightness-auto + name: Auto + preset_mode: Auto + show_name: false + show_state: false + show_toolbar: true + stats: + - entity_id: sensor.bedroom_purifier_temperature + unit: "\xB0C" + - entity_id: sensor.bedroom_purifier_humidity + unit: '%' + - entity_id: sensor.bedroom_purifier_filter_life_remaining + subtitle: Filter Remaining + unit: '%' + type: custom:purifier-card + - chips: + - entity: binary_sensor.in_bed + type: entity + type: custom:mushroom-chips-card + icon: mdi:bed + path: bedroom + theme: Backend-selected + title: Bedroom + - badges: [] + cards: + - entity: weather.home_weather + number_of_forecasts: '3' + type: custom:weather-card + - entities: + - entity: sun.sun + - entity: sensor.home_weather_condition + - entity: sensor.home_weather_temperature + name: "\xB0C Current" + - entity: sensor.home_weather_humidity + name: Humidity + - entity: sensor.home_weather_cloud_coverage + name: Cloud coverage + hours_to_show: 24 + refresh_interval: 0 + type: history-graph + - center_latitude: -36.7769283 + center_longitude: 144.2634146 + extra_labels: true + map_style: Voyager + marker_latitude: -36.7769283 + marker_longitude: 144.2634146 + show_marker: true + show_range: true + show_zoom: true + type: custom:bom-radar-card + zoom_level: 8 + icon: hass:thermometer + path: climate + title: Climate + - badges: + - entity: sensor.electricity_general_price + - entity: sensor.eagle_200_meter_power_demand + cards: + - link_dashboard: true + type: energy-distribution + - apex_config: + chart: + height: 250 + type: area + dataLabels: + enabled: false + fill: + gradient: + inverseColors: false + opacityFrom: 0.45 + opacityTo: 0.05 + shadeIntensity: 1 + stops: + - 20 + - 100 + - 100 + - 100 + type: gradient + legend: + show: false + stroke: + curve: smooth + show: true + width: 2 + xaxis: + labels: + datetimeFormatter: + day: ddd + month: ddd + type: datetime + graph_span: 35h + header: + colorize_states: true + show: true + show_states: true + title: Amber Price 24hrs + now: + color: red + label: Now + show: true + series: + - color: black + curve: smooth + entity: sensor.electricity_general_price + extend_to_end: false + name: Price + type: area + yaxis_id: price + - color: lightgrey + data_generator: "return entity.attributes.forecasts.map((entry) => {\n return\ + \ [new Date(entry.start_time), entry.per_kwh];\n});\n" + entity: sensor.electricity_general_forecast + extend_to_end: false + name: Predicted Price + show: + in_chart: true + in_header: false + type: area + yaxis_id: price + - color: green + curve: smooth + entity: sensor.electricity_renewables + extend_to_end: false + name: Renewables in Grid + show: + in_chart: true + in_header: true + type: area + unit: '%' + yaxis_id: renewables_perc + - color: lightgreen + curve: smooth + data_generator: "return entity.attributes.forecasts.map((entry) => {\n return\ + \ [new Date(entry.start_time), entry.renewables];\n});\n" + entity: sensor.electricity_general_forecast + extend_to_end: false + name: Renewables in Grid + show: + in_chart: true + in_header: false + type: area + unit: '%' + yaxis_id: renewables_perc + - color: grey + entity: sensor.electricity_general_forecast + extend_to_end: false + name: Predicted Price + show: + in_chart: false + in_header: true + type: area + yaxis_id: price + span: + offset: -24h + start: minute + type: custom:apexcharts-card + yaxis: + - id: price + max: ~1 + min: ~-1 + - id: renewables_perc + max: ~100 + min: ~0 + opposite: true + - entities: + - entity: sensor.eagle_200_meter_power_demand + name: Meter Power Demand + secondary_info: last-changed + - entity: sensor.electricity_renewables + secondary_info: last-changed + - entity: binary_sensor.electricity_price_spike + secondary_info: last-changed + - entity: sensor.electricity_general_price + secondary_info: last-changed + - entity: sensor.electricity_general_forecast + type: entities + - cards: + - entity: sensor.eagle_200_meter_power_demand + max: 5 + min: 0 + name: Current Usage + needle: true + severity: + green: 0 + red: 3 + yellow: 1.5 + type: gauge + - entity: sensor.electricity_general_price + max: 2 + min: 0 + name: Current Price + needle: true + severity: + green: -1 + red: 0.65 + yellow: 0.25 + type: gauge + unit: $ + type: horizontal-stack + - entity: sensor.current_electricity_cost + max: 5 + min: 0 + name: Current Cost + needle: true + severity: + green: -1000 + red: 1.5 + yellow: 0.75 + type: gauge + - entities: + - entity: sensor.eagle_200_meter_power_demand + - entity: sensor.electricity_general_price + - entity: sensor.current_electricity_cost + - entity: sensor.eagle_200_net_meter_energy_delivered_minus_received + hours_to_show: 24 + refresh_interval: 5 + type: history-graph + - card: + type: history-graph + filter: + exclude: + - name: /UPS/ + - name: /Eagle-200/ + - name: /Estimated Power Production/ + - state: unavailable + include: + - attributes: + device_class: power + - attributes: + device_class: xxdisabled_voltage + - attributes: + device_class: current + type: custom:auto-entities + unique: true + - card: + show_header_toggle: false + type: entities + filter: + exclude: + - name: /Restart/ + - state: unavailable + include: + - device: /power|plug/ + domain: switch + options: + secondary_info: last-changed + show_empty: false + sort: + method: friendly_name + type: custom:auto-entities + unique: true + - type: energy-devices-graph + - type: energy-usage-graph + - card: + hours_to_show: 3 + title: Voltage + type: history-graph + filter: + exclude: + - entity_id: /nas_ups/ + - entity_id: /battery/ + - entity_id: /dht/ + include: + - entity_id: /voltage/ + type: custom:auto-entities + - entities: + - sensor.co2_intensity + type: history-graph + icon: hass:lightning-bolt + path: power + title: Power + - badges: [] + cards: + - calibration_source: + camera: true + entity: vacuum.robot_vacuum + map_source: + camera: camera.vacuum_map + type: custom:xiaomi-vacuum-map-card + vacuum_platform: default + icon: '' + panel: false + path: misc + title: misc + - badges: [] + cards: + - entities: + - switch.washing_machine_plug + - sensor.washing_machine_plug_current + - sensor.washing_machine_plug_energy_usage + - sensor.washing_machine_plug_total_daily_energy + - sensor.washing_machine_plug_voltage + - sensor.washing_machine_plug_wattage + hours_to_show: 120 + type: history-graph + icon: mdi:washing-machine + path: washing + theme: Backend-selected + title: Washing + - badges: [] + cards: + - card: + type: entities + filter: + exclude: + - entity_id: /tent/ + include: + - entity_id: /adaptive/ + type: custom:auto-entities + - card: + type: entities + filter: + exclude: + - entity_id: /tent/ + include: + - domain: light + type: custom:auto-entities + icon: mdi:lamps + path: lighting + theme: Backend-selected + title: Lighting + - badges: [] + cards: + - card: + type: entities + filter: + exclude: [] + include: + - attributes: + device_class: door + domain: binary_sensor + type: custom:auto-entities + - card: + type: history-graph + filter: + exclude: [] + include: + - attributes: + device_class: door + domain: binary_sensor + type: custom:auto-entities + icon: mdi:door + path: doors + theme: Backend-selected + title: Doors diff --git a/lovelace/lovelace_dashboards.yaml b/lovelace/lovelace_dashboards.yaml new file mode 100644 index 0000000..9dfc57e --- /dev/null +++ b/lovelace/lovelace_dashboards.yaml @@ -0,0 +1,43 @@ +items: +- icon: mdi:greenhouse + id: lovelace_shed + mode: storage + require_admin: true + show_in_sidebar: true + title: Shed + url_path: lovelace-shed +- icon: mdi:chair-rolling + id: bos_office + mode: storage + require_admin: false + show_in_sidebar: true + title: Bo's Office + url_path: bos-office +- icon: mdi:leak + id: lovelace_sensors + mode: storage + require_admin: true + show_in_sidebar: true + title: Sensors + url_path: lovelace-sensors +- icon: mdi:printer-3d + id: 3d_printing + mode: storage + require_admin: false + show_in_sidebar: true + title: 3D Printing + url_path: 3d-printing +- icon: mdi:nas + id: lovelace_servers + mode: storage + require_admin: true + show_in_sidebar: true + title: Servers + url_path: lovelace-servers +- icon: mdi:shovel + id: lovelace_gardens + mode: storage + require_admin: false + show_in_sidebar: true + title: Gardening + url_path: lovelace-gardens diff --git a/lovelace/lovelace_resources.yaml b/lovelace/lovelace_resources.yaml new file mode 100644 index 0000000..e584022 --- /dev/null +++ b/lovelace/lovelace_resources.yaml @@ -0,0 +1,118 @@ +items: +- id: e23c91b83b6846ad9b473961a4ae62a8 + type: module + url: /hacsfiles/mini-graph-card/mini-graph-card-bundle.js?hacstag=1512800620110 +- id: 286fca3cd80f4192b815b715ef5f999e + type: module + url: /hacsfiles/vertical-stack-in-card/vertical-stack-in-card.js?hacstag=142051833042 +- id: 032c18f548ea467b8bce3884fe451d82 + type: module + url: /hacsfiles/vacuum-card/vacuum-card.js?hacstag=261291295263 +- id: dc13a5629c8a409dad2800cca63fb016 + type: module + url: /hacsfiles/weather-card/weather-card.js +- id: 45a0fbe9612d4dbba973037d3d0edc99 + type: module + url: /hacsfiles/upcoming-media-card/upcoming-media-card.js +- id: 69e31fab8ea64da890a5c68fc590320f + type: module + url: /hacsfiles/lovelace-xiaomi-vacuum-map-card/xiaomi-vacuum-map-card.js?hacstag=1933720442011 +- id: f2b643a296014c8292cbb3ba1b9af69b + type: module + url: /hacsfiles/kb-better-graph-colors/kb-better-graph-colors.js +- id: 2e5860691cc745788c82d4c7c653a6ce + type: module + url: /hacsfiles/purifier-card/purifier-card.js?hacstag=274738925223 +- id: c623d3fc8954431685d17cd75bf572bb + type: module + url: /hacsfiles/apexcharts-card/apexcharts-card.js?hacstag=331701152201 +- id: 4cb20baf31e442e9830e4af74f089a0d + type: module + url: /hacsfiles/lovelace-auto-entities/auto-entities.js?hacstag=1677445841110 +- id: 8468c5604c2d41d294fb0143cea43765 + type: module + url: /hacsfiles/simple-thermostat/simple-thermostat.js?hacstag=158654878243 +- id: 8509de9391a14572a0db603819537c07 + type: module + url: /hacsfiles/battery-state-card/battery-state-card.js?hacstag=256292682211 +- id: 897bd05d2acb4477ac0a46b5bdc93092 + type: module + url: /hacsfiles/lovelace-slider-entity-row/slider-entity-row.js?hacstag=1448997001721 +- id: 1536273745f94b7cbde611f1c4d24f55 + type: module + url: /hacsfiles/config-template-card/config-template-card.js?hacstag=172177543136 +- id: 5d39e72495dd4156b26445d85c3041f0 + type: module + url: /hacsfiles/lovelace-swipe-navigation/swipe-navigation.js?hacstag=183995552136 +- id: d612f620a56f4bacb5ce3a10353074dc + type: module + url: /hacsfiles/lovelace-state-switch/state-switch.js?hacstag=158756598193 +- id: 002ab8e9552e45219e21acb08280a8f2 + type: module + url: /hacsfiles/miflora-card/miflora-card.js?hacstag=197715418010 +- id: ddb6d1b21fc44ae692519ea38c9cf9cb + type: module + url: /hacsfiles/bom-radar-card/bom-radar-card.js?hacstag=294609880202 +- id: edc63027be67460bab526d3dd3b4a8b2 + type: module + url: /hacsfiles/secondaryinfo-entity-row/secondaryinfo-entity-row.js?hacstag=15971160550 +- id: 3c56eec3ea2148b3874c5bd0edf268f9 + type: module + url: /hacsfiles/canvas-gauge-card/canvas-gauge-card.js?hacstag=142545838041 +- id: 561282ddf74a46b79ec41d6c8ced3309 + type: module + url: /hacsfiles/lovelace-layout-card/layout-card.js?hacstag=156434866242 +- id: b573b075ef40439ea3961ecd46ea285a + type: module + url: /hacsfiles/scheduler-card/scheduler-card.js?hacstag=286270157234 +- id: 618ee66f432c46edbbf612f2c10faa28 + type: module + url: /hacsfiles/lovelace-multiple-entity-row/multiple-entity-row.js?hacstag=178921037441 +- id: 81a60ba42b6b4bb5905815f9e923694f + type: module + url: /hacsfiles/lovelace-fold-entity-row/fold-entity-row.js?hacstag=150781994220 +- id: 875ce0fef3404755b1f0e5ae45533de5 + type: module + url: /hacsfiles/lovelace-card-tools/card-tools.js?hacstag=16140332811 +- id: 74a6c45f816b471f95d8bda2d18515e6 + type: module + url: /hacsfiles/restriction-card/restriction-card.js?hacstag=215633404127 +- id: 6b5e206532c64526991bbbd84b993316 + type: module + url: /hacsfiles/hass-bha-icons/hass-bha-icons.js?hacstag=17980857697739 +- id: f8fc07fca3fa4274be5f46d82400787c + type: module + url: /hacsfiles/thermal_comfort_icons/thermal_comfort_icons.js?hacstag=449218690130 +- id: eb1d61035e6b490bb4137c28de0193dd + type: module + url: /hacsfiles/flex-horseshoe-card/flex-horseshoe-card.js?hacstag=207292725090 +- id: 272b9dafed404fa88e51858b7df79041 + type: module + url: /hacsfiles/lovelace-time-picker-card/time-picker-card.js?hacstag=261262884121 +- id: 17610f86804c432aafbd0bbd93622916 + type: module + url: /hacsfiles/lovelace-paper-buttons-row/paper-buttons-row.js?hacstag=244872232100 +- id: 78939a4781bd40f6accb3cba860a100f + type: module + url: /hacsfiles/lovelace-mushroom/mushroom.js?hacstag=444350375180 +- id: 4795f91c6d3a4fd3a5b1900f9990217e + type: module + url: /hacsfiles/stack-in-card/stack-in-card.js?hacstag=248954055020 +- id: bb19fc1aeaae4fab848a25a40054be8c + type: module + url: /hacsfiles/lovelace-template-entity-row/template-entity-row.js?hacstag=231674882130 +- id: 6257884b5ef24cb080834b14e5d22b28 + type: module + url: /hacsfiles/lovelace-card-templater/lovelace-card-templater.js?hacstag=1843331630017 +- id: 820e37c6795c46ff80c94abb56c9aa8a + type: module + url: /hacsfiles/garbage-collection-card/garbage-collection-card.js?hacstag=2070182001201 +- id: 8e77c60a655f4bd9982025fb278fffef + type: module + url: /hacsfiles/lovelace-battery-entity-row/battery-entity-row.js?hacstag=303857065131 +- id: 867c82efa08d47a3a9ccbe9f5afb238a + type: module + url: /hacsfiles/numberbox-card/numberbox-card.js?hacstag=304967918310 +- id: 6a72c3dfa03446ffae4b9d8093bb5b7a + type: module + url: /hacsfiles/custom-ui/custom-ui.js?hacstag=267558148202204191 diff --git a/node-red/flows.json b/node-red/flows.json new file mode 100644 index 0000000..27d0805 --- /dev/null +++ b/node-red/flows.json @@ -0,0 +1 @@ +[{"id":"466ad5c2.a29164","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"40da5ad2.8aabf4","type":"tab","label":"Covid-19","disabled":false,"info":""},{"id":"dc09bc1e.a5f7f","type":"server","name":"Home Assistant","addon":true},{"id":"f2eef645.6063f","type":"binance-credentials","name":"Binance Credentials"},{"id":"4f147b45.6d1a5c","type":"http request","z":"40da5ad2.8aabf4","name":"state cases","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://raw.githubusercontent.com/covid-19-au/covid-19-au.github.io/prod/src/data/stateCaseData.json","tls":"","persist":false,"proxy":"","authType":"","x":270,"y":160,"wires":[["d3ee7ba9.942948"]]},{"id":"d3ee7ba9.942948","type":"change","z":"40da5ad2.8aabf4","name":"just victoria data","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.values[2]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":160,"wires":[["30249d2b.adadf2"]]},{"id":"3af185ab.c301b2","type":"ha-entity","z":"40da5ad2.8aabf4","name":"COVID-19","server":"dc09bc1e.a5f7f","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"COVID-19 Data"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:virus"},{"property":"unit_of_measurement","value":""}],"state":"payload[1]","stateType":"msg","attributes":[{"property":"state","value":"payload[0]","valueType":"msg"},{"property":"cases","value":"payload[1]","valueType":"msg"},{"property":"deaths","value":"payload[2]","valueType":"msg"},{"property":"recovered","value":"payload[3]","valueType":"msg"},{"property":"tested","value":"payload[4]","valueType":"msg"},{"property":"active","value":"payload[5]","valueType":"msg"},{"property":"hospital","value":"payload[6]","valueType":"msg"},{"property":"icu","value":"payload[7]","valueType":"msg"}],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":970,"y":160,"wires":[[]]},{"id":"366ac0f2.d26968","type":"inject","z":"40da5ad2.8aabf4","name":"","repeat":"3600","crontab":"","once":true,"onceDelay":"30","topic":"","payload":"","payloadType":"date","x":110,"y":160,"wires":[["4f147b45.6d1a5c"]]},{"id":"30249d2b.adadf2","type":"rbe","z":"40da5ad2.8aabf4","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":590,"y":160,"wires":[["3af185ab.c301b2"]]},{"id":"6aaac257.edb40c","type":"http request","z":"40da5ad2.8aabf4","name":"state cases","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://raw.githubusercontent.com/covid-19-au/covid-19-au.github.io/prod/src/data/state.json","tls":"","persist":false,"proxy":"","authType":"","x":270,"y":260,"wires":[["882d669e.5f14c8"]]},{"id":"23c16912.20f496","type":"inject","z":"40da5ad2.8aabf4","name":"","repeat":"3600","crontab":"","once":true,"onceDelay":"30","topic":"","payload":"","payloadType":"date","x":110,"y":260,"wires":[["6aaac257.edb40c"]]},{"id":"482885aa.9fabbc","type":"comment","z":"40da5ad2.8aabf4","name":"Data Source Site","info":"Data source:\nhttps://github.com/covid-19-au/covid-19-au.github.io\n\nVictorian source:\nhttps://interactive.guim.co.uk/covidfeeds/victoria.json","x":100,"y":60,"wires":[]},{"id":"4eeb6da3.14ce6c","type":"ha-entity","z":"40da5ad2.8aabf4","name":"COVID-19 New Cases","server":"dc09bc1e.a5f7f","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"COVID-19 New"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:virus"},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":1000,"y":260,"wires":[[]]},{"id":"4141ba11.d94e34","type":"http request","z":"40da5ad2.8aabf4","name":"locale cases","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://interactive.guim.co.uk/covidfeeds/victoria.json","tls":"","persist":false,"proxy":"","authType":"","x":270,"y":460,"wires":[["9f89f5ee.bb3dd8"]]},{"id":"62431127.2d61d","type":"inject","z":"40da5ad2.8aabf4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"3600","crontab":"","once":true,"onceDelay":"30","topic":"","payload":"","payloadType":"date","x":110,"y":460,"wires":[["4141ba11.d94e34"]]},{"id":"9f89f5ee.bb3dd8","type":"change","z":"40da5ad2.8aabf4","name":"locale","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload[45]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":460,"wires":[["5a22148b.f4b4ec"]]},{"id":"5a22148b.f4b4ec","type":"rbe","z":"40da5ad2.8aabf4","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":590,"y":460,"wires":[["977b4662.8b88"]]},{"id":"977b4662.8b88","type":"change","z":"40da5ad2.8aabf4","name":"only case count data","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.count","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":460,"wires":[["a95a84ad.096a78"]]},{"id":"a95a84ad.096a78","type":"ha-entity","z":"40da5ad2.8aabf4","name":"COVID-19 Local","server":"dc09bc1e.a5f7f","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"COVID-19 Local"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:home"},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":980,"y":460,"wires":[[]]},{"id":"878cd05b.e1db5","type":"comment","z":"40da5ad2.8aabf4","name":"Edit the above payload [] to change the locale displayed","info":"","x":450,"y":520,"wires":[]},{"id":"882d669e.5f14c8","type":"rbe","z":"40da5ad2.8aabf4","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":590,"y":260,"wires":[["564b2fa5.94e01","6d58927c.e10314"]]},{"id":"564b2fa5.94e01","type":"function","z":"40da5ad2.8aabf4","name":"Get Vic Cases Daily","func":"var total = Object.keys(msg.payload).length;\n//var difference = msg.payload[total-1].VIC-msg.payload[total-2].VIC;\n//return {payload:difference};\n\nvar input = msg.payload;\nvar data = [], date;\n\nfor (date in msg.payload) {\n data.push(date);\n}\n\nvar today = data[data.length-1];// - data[data.length-2];\nvar yesterday = data[data.length-2];\n\nvar result = input[today].VIC[0] - input[yesterday].VIC[0];\n\n//return {payload:msg.payload[total-1]};\nreturn {payload:result};","outputs":1,"noerr":0,"initialize":"","finalize":"","x":780,"y":260,"wires":[["4eeb6da3.14ce6c"]]},{"id":"6d58927c.e10314","type":"function","z":"40da5ad2.8aabf4","name":"Fortnight Average","func":"var input = msg.payload;\nvar data = [], date;\n\nfor (date in msg.payload) {\n data.push(date);\n}\n\nvar last14days = 0;\n\nfor (i = 1; i < 15; i++)\n{\n last14days += input[data[data.length-i]].VIC[0] - input[data[data.length-i-1]].VIC[0];\n}\n\nvar result = last14days / 14;\n\nreturn {payload:result};","outputs":1,"noerr":0,"initialize":"","finalize":"","x":770,"y":320,"wires":[["3fc3c1ba.d26796"]]},{"id":"3fc3c1ba.d26796","type":"ha-entity","z":"40da5ad2.8aabf4","name":"Covid Average","server":"dc09bc1e.a5f7f","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Covid Average"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:calendar"},{"property":"unit_of_measurement","value":""}],"state":"payload","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","x":980,"y":320,"wires":[[]]},{"id":"5b7c2205.274ebc","type":"binance-get-balance","z":"466ad5c2.a29164","name":"","binance":"f2eef645.6063f","x":460,"y":420,"wires":[["fe301e63.6fe"]]},{"id":"fe301e63.6fe","type":"debug","z":"466ad5c2.a29164","name":"","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":750,"y":400,"wires":[]},{"id":"192d88e5.a61f4f","type":"inject","z":"466ad5c2.a29164","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":200,"y":540,"wires":[["5b7c2205.274ebc"]]}] diff --git a/node-red/settings.js b/node-red/settings.js new file mode 100644 index 0000000..6eb103e --- /dev/null +++ b/node-red/settings.js @@ -0,0 +1,193 @@ +/** + * Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +/** + * PLEASE NOTE! IMPORTANT! READ! + * + * This is a modified version of the settings file. Some parts of the + * settings are actually controlled by the Home Assistant add-on. + * + * Parts that are handled by it, are removed from this settings template. + * The following configuration keys are controlled by the add-on and removed. + * + * - uiPort (port setting in the add-on log) + * - uiHost (no need to manually configure this in the add-on) + * - debugUseColors (disabled, won't work in the add-on) + * - flowFile (fixed to flows.json) + * - credentialSecret (credentials_secret in the add-on configuration) + * - userDir (is set fixed to `/config/node-red`) + * - nodesDir (is set fixed to `/config/node-red/nodes`) + * - adminAuth (known as users in the add-on configuration) + * - https (ssl settings in the add-on configuration) + * - logging.console.level (log_level in the add-on configuration) + * - httpNodeAuth (http_node settings in the add-on configuration) + * - httpStaticAuth (http_static settings in the add-on configuration) + * - requireHttps (require_ssl setting in the add-on configuration) + * - httpNodeRoot (set fixed to `/endpoint` ) + * + * If you like to change those settings, some are available via the add-on + * settings/option in the Supervisor panel in Home Assistant. + */ + +module.exports = { + // Retry time in milliseconds for MQTT connections + mqttReconnectTime: 15000, + + // Retry time in milliseconds for Serial port connections + serialReconnectTime: 15000, + + // Retry time in milliseconds for TCP socket connections + //socketReconnectTime: 10000, + + // Timeout in milliseconds for TCP server socket connections + // defaults to no timeout + //socketTimeout: 120000, + + // Timeout in milliseconds for HTTP request connections + // defaults to 120 seconds + //httpRequestTimeout: 120000, + + // The maximum length, in characters, of any message sent to the debug sidebar tab + debugMaxLength: 1000, + + // The maximum number of messages nodes will buffer internally as part of their + // operation. This applies across a range of nodes that operate on message sequences. + // defaults to no limit. A value of 0 also means no limit is applied. + //nodeMaxMessageBufferLength: 0, + + // To disable the option for using local files for storing keys and certificates in the TLS configuration + // node, set this to true + //tlsConfigDisableLocalFiles: true, + + // By default, the Node-RED UI is available at http://localhost:1880/ + // The following property can be used to specify a different root path. + // If set to false, this is disabled. + //httpAdminRoot: '/admin', + + // The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot', + // to apply the same root to both parts. + //httpRoot: '/red', + + // When httpAdminRoot is used to move the UI to a different root path, the + // following property can be used to identify a directory of static content + // that should be served at http://localhost:1880/. + //httpStatic: '/home/nol/node-red-static/', + + // The maximum size of HTTP request that will be accepted by the runtime api. + // Default: 5mb + //apiMaxLength: '5mb', + + // If you installed the optional node-red-dashboard you can set it's path + // relative to httpRoot + //ui: { path: "ui" }, + + // The following property can be used to disable the editor. The admin API + // is not affected by this option. To disable both the editor and the admin + // API, use either the httpRoot or httpAdminRoot properties + //disableEditor: false, + + // The following property can be used to configure cross-origin resource sharing + // in the HTTP nodes. + // See https://github.com/troygoode/node-cors#configuration-options for + // details on its contents. The following is a basic permissive set of options: + //httpNodeCors: { + // origin: "*", + // methods: "GET,PUT,POST,DELETE" + //}, + + // If you need to set an http proxy please set an environment variable + // called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. + // For example - http_proxy=http://myproxy.com:8080 + // (Setting it here will have no effect) + // You may also specify no_proxy (or NO_PROXY) to supply a comma separated + // list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk + + // The following property can be used to add a custom middleware function + // in front of all http in nodes. This allows custom authentication to be + // applied to all http in nodes, or any other sort of common request processing. + //httpNodeMiddleware: function(req,res,next) { + // // Handle/reject the request, or pass it on to the http in node by calling next(); + // // Optionally skip our rawBodyParser by setting this to true; + // //req.skipRawBodyParser = true; + // next(); + //}, + + // The following property can be used to verify websocket connection attempts. + // This allows, for example, the HTTP request headers to be checked to ensure + // they include valid authentication information. + //webSocketNodeVerifyClient: function(info) { + // // 'info' has three properties: + // // - origin : the value in the Origin header + // // - req : the HTTP request + // // - secure : true if req.connection.authorized or req.connection.encrypted is set + // // + // // The function should return true if the connection should be accepted, false otherwise. + // // + // // Alternatively, if this function is defined to accept a second argument, callback, + // // it can be used to verify the client asynchronously. + // // The callback takes three arguments: + // // - result : boolean, whether to accept the connection or not + // // - code : if result is false, the HTTP error status to return + // // - reason: if result is false, the HTTP reason string to return + //}, + + // Anything in this hash is globally available to all functions. + // It is accessed as context.global. + // eg: + // functionGlobalContext: { os:require('os') } + // can be accessed in a function block as: + // context.global.os + + functionGlobalContext: { + // os:require('os'), + // jfive:require("johnny-five"), + // j5board:require("johnny-five").Board({repl:false}) + }, + + // The following property can be used to order the categories in the editor + // palette. If a node's category is not in the list, the category will get + // added to the end of the palette. + // If not set, the following default order is used: + paletteCategories: [ + "home_assistant", + "subflows", + "common", + "function", + "network", + "sequence", + "parser", + "storage", + ], + + // Configure the logging output + logging: { + // Only console logging is currently supported + console: { + // Whether or not to include metric events in the log output + metrics: false, + // Whether or not to include audit events in the log output + audit: false, + }, + }, + + // Customising the editor + editorTheme: { + projects: { + // To enable the Projects feature, set this value to true + enabled: false, + }, + }, +};