diff --git a/configuration.yaml b/configuration.yaml index 46da2f8..bc7f114 100644 --- a/configuration.yaml +++ b/configuration.yaml @@ -60,47 +60,6 @@ calendar: - name: 'Due This Week' due_date_days: 7 -notify: - - platform: ios - - name: all_ios - platform: group - services: - - service: mobile_app_tinas_iphone - - service: mobile_app_tony_s_iphone - - service: mobile_app_tony_s_ipad - - service: mobile_app_kallen_iphone - - name: ios_parents - platform: group - services: - - service: mobile_app_tinas_iphone - - service: mobile_app_tony_s_ipad - - service: mobile_app_tony_s_iphone - - name: ios_tony - platform: group - services: - - service: mobile_app_tony_s_ipad - - service: mobile_app_tony_s_iphone - - name: ios_tina - platform: group - services: - - service: mobile_app_tinas_iphone - - name: ios_kallen - platform: group - services: - - service: mobile_app_kallen_iphone - - name: ios_nerds - platform: group - services: - - service: mobile_app_kallen_iphone - - service: mobile_app_tony_s_ipad - - service: mobile_app_tony_s_iphone - - name: tv_notifications - platform: group - services: - - service: living_room_tv - - service: basement_tv - - service: master_bedroom_tv - rest_command: todoist: method: post diff --git a/input_boolean.yaml b/input_boolean.yaml index ef7d644..bc3fdb7 100644 --- a/input_boolean.yaml +++ b/input_boolean.yaml @@ -13,3 +13,6 @@ shuffle_spotify: tornado_watch: name: Tornado Watch icon: mdi:message-alert +vacation_mode: + name: Vacation Mode + icon: mdi:umbrella-beach \ No newline at end of file diff --git a/packages/events.yaml b/packages/events.yaml index e0a6517..6d09297 100644 --- a/packages/events.yaml +++ b/packages/events.yaml @@ -1,10 +1,3 @@ -############################################################################### -# @author : Jeffrey Stone -# @date : 02/19/2019 -# @package : Events -# @description : Special Events. -############################################################################### - input_boolean: school_in_session: name: School In Session @@ -98,40 +91,40 @@ sensor: {%- endif %} automation: - - id: refresh_special_event_sensors - alias: Refresh special event sensors - initial_state: true - trigger: - - platform: time - at: '00:00:01' - - platform: homeassistant - event: start - action: - - service: python_script.special_events - data: - name: Tony - type: birthday - date: !secret tony_bday - - service: python_script.special_events - data: - name: Tina - type: birthday - date: !secret tina_bday - - service: python_script.special_events - data: - name: Kallen - type: birthday - date: !secret kallen_bday - - service: python_script.special_events - data: - name: Emmalynn - type: birthday - date: !secret emmalynn_bday - - service: python_script.special_events - data: - name: Our Anniversary - type: anniversary - date: !secret wedding_anniversary + # - id: refresh_special_event_sensors + # alias: Refresh special event sensors + # initial_state: true + # trigger: + # - platform: time + # at: '00:00:01' + # - platform: homeassistant + # event: start + # action: + # - service: python_script.special_events + # data: + # name: Tony + # type: birthday + # date: !secret tony_bday + # - service: python_script.special_events + # data: + # name: Tina + # type: birthday + # date: !secret tina_bday + # - service: python_script.special_events + # data: + # name: Kallen + # type: birthday + # date: !secret kallen_bday + # - service: python_script.special_events + # data: + # name: Emmalynn + # type: birthday + # date: !secret emmalynn_bday + # - service: python_script.special_events + # data: + # name: Our Anniversary + # type: anniversary + # date: !secret wedding_anniversary - id: e1cb2d02-0423-11eb-adc1-0242ac120002 alias: School today diff --git a/packages/integrations.yaml b/packages/integrations.yaml index 7894f53..e426128 100644 --- a/packages/integrations.yaml +++ b/packages/integrations.yaml @@ -37,6 +37,14 @@ tts: time_memory: 300 base_url: !secret remote_url service_name: google_say + - platform: amazon_polly + aws_access_key_id: !secret aws_access_key_id + aws_secret_access_key: !secret aws_secret_access_key + region_name: 'us-east-1' + text_type: ssml + voice: Joanna + cache: true + engine: neural google: client_id: !secret google_client_id diff --git a/packages/jarvis.yaml b/packages/jarvis.yaml new file mode 100644 index 0000000..add2656 --- /dev/null +++ b/packages/jarvis.yaml @@ -0,0 +1,82 @@ +# Original author information below. Could not have done this without his awesome videos! + +############################################################################### +# @author : Jeffrey Stone +# @date : 07/09/2019 +# @package : Jarvis +# @description : Bringing some Jarvis to Home Assistant +############################################################################### + +input_boolean: + house_party_protocol_switch: + name: House Party Switch + +# automation: +# - id: house_party_protocol_on +# alias: Turn On House Party Protocol +# initial_state: true +# trigger: +# - platform: state +# entity_id: input_boolean.house_party_protocol_switch +# to: 'on' +# action: +# - delay: 00:00:05 +# - service: homeassistant.turn_on +# entity_id: group.incense +# - service: script.status_annc +# data_template: +# who: '{{ states.sensor.room_presence.state }}' +# call_house_party_protocol_enabled: 1 + +# - id: house_party_protocol_off +# alias: Turn Off House Party Protocol +# initial_state: true +# trigger: +# - platform: state +# entity_id: input_boolean.house_party_protocol_switch +# to: 'off' +# action: +# - delay: 00:00:05 +# - service: homeassistant.turn_off +# entity_id: group.incense +# - service: script.status_annc +# data_template: +# who: '{{ states.sensor.room_presence.state }}' +# call_house_party_protocol_disabled: 1 + +script: + house_party_protocol_on: + sequence: + - delay: 00:00:05 + - service: homeassistant.turn_on + entity_id: group.incense + - service: script.status_annc + data_template: + who: '{{ states.sensor.room_presence.state }}' + call_house_party_protocol_enabled: 1 + + house_party_protocol_off: + sequence: + - delay: 00:00:05 + - service: homeassistant.turn_off + entity_id: group.incense + - service: script.status_annc + data_template: + who: '{{ states.sensor.room_presence.state }}' + call_house_party_protocol_disabled: 1 + + alexa_interjection: + sequence: + - service: script.status_annc + data: + who: "{{ states('sensor.last_alexa')}}" + call_confirmation: 1 + + google_interjection: + sequence: + - service: script.status_annc + data: + who: '{{ states.sensor.room_audio.state }}' + call_confirmation: 1 + + diff --git a/packages/notify.yaml b/packages/notify.yaml index 3f2309b..a9c5023 100644 --- a/packages/notify.yaml +++ b/packages/notify.yaml @@ -1,6 +1,35 @@ # ATTENTION: The actual notify services are currently defined in configuration.yaml and NOT in this file. # Just a note because I've already forgotten once ;) +############################################################################### +# AWS Polly Options: +# pause: +# +# emphasis: +# really like +# level attribute values: +# Strong: Increases the volume and slows the speaking rate so that the speech is louder and slower. +# Moderate: Increases the volume and slows the speaking rate, but less than strong. Moderate is the default. +# Reduced: Decreases the volume and speeds up the speaking rate. Speech is softer and faster. +# Pause Between Paragraphs: +# Wrap text in

+# Adding a Pause Between Sentences: +# Ending a sentence with a period (.) +# Controlling How Special Types of Words Are Spoken: +# [text to be interpreted] +# characters or spell-out: Spells out each letter of the text, as in a-b-c. +# cardinal or number: Interprets the numerical text as a cardinal number, as in 1,234. +# ordinal: Interprets the numerical text as an ordinal number, as in 1,234th. +# digits: Spells out each digit individually, as in 1-2-3-4. +# fraction: Interprets the numerical text as a fraction. This works for both common fractions such as 3/20, and mixed fractions, such as 2 ½. See below for more information. +# unit: Interprets a numerical text as a measurement. The value should be either a number or a fraction followed by a unit with no space in between as in 1/2inch, or by just a unit, as in 1meter. +# date: Interprets the text as a date. The format of the date must be specified with the format attribute. See below for more information. +# time: Interprets the numerical text as duration, in minutes and seconds, as in 1'21". +# address: Interprets the text as part of a street address. +# expletive: "Beeps out" the content included within the tag. +# telephone: Interprets the numerical text as a 7-digit or 10-digit telephone number, as in 2025551212. You can also use this value for handle telephone extensions, as in 2025551212x345. See below for more information. +################################################################################ + input_boolean: text_notify_tony: name: Send Texts to Tony @@ -43,6 +72,48 @@ input_boolean: debug_texts: name: Debug Texts +notify: + - platform: ios + - name: all_ios + platform: group + services: + - service: mobile_app_tinas_iphone + - service: mobile_app_tony_s_iphone + - service: mobile_app_tony_s_ipad + - service: mobile_app_kallen_iphone + - name: ios_parents + platform: group + services: + - service: mobile_app_tinas_iphone + - service: mobile_app_tony_s_ipad + - service: mobile_app_tony_s_iphone + - name: ios_tony + platform: group + services: + - service: mobile_app_tony_s_ipad + - service: mobile_app_tony_s_iphone + - name: ios_tina + platform: group + services: + - service: mobile_app_tinas_iphone + - name: ios_kallen + platform: group + services: + - service: mobile_app_kallen_iphone + - name: ios_nerds + platform: group + services: + - service: mobile_app_kallen_iphone + - service: mobile_app_tony_s_ipad + - service: mobile_app_tony_s_iphone + - name: tv_notifications + platform: group + services: + - service: living_room_tv + - service: basement_tv + - service: master_bedroom_tv + + script: @@ -227,3 +298,371 @@ script: # badge: 0 # category: '{{ ios_category }}' # entity_id: '{{ camera_entity }}' + +############################################################################### +# Alert Notify +# Conditions: +# => Vacation mode should be off +# Services: +# => Audible +# => iOS +############################################################################### + alert_notify: + sequence: + - condition: state + entity_id: input_boolean.vacation_mode + state: 'off' + - service: tts.google_say + data_template: + entity_id: media_player.living_room_tv + message: > + {{ message }} + + jarvis_alert: + sequence: + - service: mqtt.publish + data_template: + topic: 'house/polly/lastmsg' + payload: 'This message is from {{ now().strftime("%-I") }}:{{ now().strftime("%M") }} {{ now().strftime("%p") }}. {{ message | striptags | truncate(220)}}' + retain: true + - service: media_player.turn_on + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + - service: media_player.volume_set + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + volume_level: > + {% if who == 'kallen_bedroom_speaker' %} + .60 + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + .50 + {% else %} + .50 + {% endif %} + {% endif %} + - service: tts.amazon_polly_say + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + message: >- + + + {{ message }} + + + cache: true + + + + +############################################################################### +# Voice Notify +# Conditions: +# => Only Announce when people are home. +# => Only Announce when Audible Notifications are on +############################################################################### + + speech_engine: + sequence: + - service: mqtt.publish + data_template: + topic: 'house/polly/lastmsg' + payload: 'This message is from {{ now().strftime("%-I") }}:{{ now().strftime("%M") }} {{ now().strftime("%p") }}. {{ message | striptags | truncate(220)}}' + retain: true + - service: mqtt.publish + data_template: + topic: 'house/polly/lastloc' + payload: '{{ who }}' + retain: true + - condition: state + entity_id: input_boolean.audible_notifications + state: 'on' + - condition: state + entity_id: group.family + state: 'home' + - condition: state + entity_id: input_boolean.vacation_mode + state: 'off' + - service: > + {% if voice == 'nabu' %} + script.nabu_voice + {% elif who in ['living_room_echo_dot', 'media_player.living_room_echo_dot','living_room'] %} + {% set who = 'living_room_echo_dot' %} + script.alexa_voice + {% elif who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + {% set who = 'kallen_bedroom_speaker' %} + script.jarvis_voice + {% elif who in ['master_bedroom','master_bedroom_echo_dot'] %} + {% set who = 'master_bedroom_echo_dot' %} + script.alexa_voice + {% elif who in ['basement','basement_echo_dot'] %} + {% set who = 'basement_echo_dot' %} + script.alexa_voice + {% else %} + {% set who = 'living_room_echo_dot' %} + script.alexa_voice + {% endif %} + data: + who: '{{ who }}' + message: > + {{ message }} + + + + + + # Use this Simplfied Script by calling in automaint or script like: + # service: script.speech_engine_simplified + # data: + # who: media_player.ha_blue + # #who: “{{ states(‘sensor.room_presence’) }}” + # #who: notify.kitchen_echo + # message: something to say + # + # + speech_engine_simplified: + sequence: + - condition: state + entity_id: input_boolean.audible_notifications + state: 'on' + - condition: state + entity_id: group.family + state: 'home' + - condition: state + entity_id: input_boolean.vacation_mode + state: 'off' + - service: tts.amazon_polly_say + data_template: + entity_id: >- + {{ who }} + message: >- + + + {{ message }} + + cache: true + - service: >- + {{ who }} + data: + message: > + {{ message }} + data: + type: tts + - service: tts.cloud_say + data_template: + entity_id: >- + {{ who }} + message: >- + {{ message }} + cache: true + language: en-GB + options: + gender: male + + + + # Called wheh notification needs to play on echos + alexa_voice: + sequence: + - service: media_player.turn_on + data_template: + entity_id: > + {% if who in ['living_room_echo_dot', 'media_player.living_room_echo_dot','living_room'] %} + notify.alexa_media_living_room_echo_dot + {% elif who in ['master_bedroom','master_bedroom_echo_dot'] %} + notify.alexa_media_master_bedroom_echo_dot + {% elif who in ['basement','basement_echo_dot'] %} + notify.alexa_media_basement_echo_dot + {% else %} + notify.alexa_media_living_room_echo_dot + {% endif %} + - service: media_player.volume_set + data_template: + entity_id: > + {% if who in ['living_room_echo_dot', 'media_player.living_room_echo_dot','living_room'] %} + notify.alexa_media_living_room_echo_dot + {% elif who in ['master_bedroom','master_bedroom_echo_dot'] %} + notify.alexa_media_master_bedroom_echo_dot + {% elif who in ['basement','basement_echo_dot'] %} + notify.alexa_media_basement_echo_dot + {% else %} + notify.alexa_media_living_room_echo_dot + {% endif %} + volume_level: > + {% if is_state('input_boolean.audible_notifications.state','on') %} + .6 + {% else %} + .4 + {% endif %} + - service: > + {% if who in ['living_room_echo_dot', 'media_player.living_room_echo_dot','living_room'] %} + notify.alexa_media_living_room_echo_dot + {% elif who in ['master_bedroom','master_bedroom_echo_dot'] %} + notify.alexa_media_master_bedroom_echo_dot + {% elif who in ['basement','basement_echo_dot'] %} + notify.alexa_media_basement_echo_dot + {% else %} + notify.alexa_media_living_room_echo_dot + {% endif %} + data: + message: > + {{ message }} + data: + type: tts + + # Default audible notifications. Notifcations play on the google devices. + jarvis_voice: + sequence: + - service: media_player.turn_on + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + - service: media_player.volume_set + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + volume_level: > + {% if states.input_boolean.audible_notifications.state == 'on' %} + .7 + {% else %} + .3 + {% endif %} + - service: tts.amazon_polly_say + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + message: >- + + + {{ message }} + + cache: true + + nabu_voice: + sequence: + - service: media_player.turn_on + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + - service: media_player.volume_set + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + volume_level: > + {% if states.input_boolean.audible_notifications.state == 'on' %} + .7 + {% else %} + .3 + {% endif %} + - service: tts.cloud_say + data_template: + entity_id: > + {% if who in ['kallen_bedroom','media_player.kallen_bedroom_speaker'] %} + media_player.kallen_bedroom_speaker + {% else %} + {% if states.input_boolean.audible_notifications.state == 'on' %} + media_player.living_room_tv + {% else %} + media_player.living_room_tv + {% endif %} + {% endif %} + message: >- + {{ message }} + cache: true + language: en-GB + options: + gender: male + + + # dim_main_volume: + # sequence: + # - condition: state + # entity_id: 'media_player.ha_blue' + # state: 'playing' + # - service: input_number.set_value + # data_template: + # entity_id: input_number.old_volume + # value: > + # {{ states.media_player.ha_blue.attributes.volume_level }} + # - service: media_player.volume_set + # data_template: + # entity_id: media_player.ha_blue + # volume_level: .2 + + # raise_main_volume: + # sequence: + # - condition: state + # entity_id: 'media_player.ha_blue' + # state: 'playing' + # - service: media_player.volume_set + # data_template: + # entity_id: media_player.ha_blue + # volume_level: > + # {{ states.input_number.old_volume.state }} diff --git a/packages/speech.yaml b/packages/speech.yaml new file mode 100644 index 0000000..8b28582 --- /dev/null +++ b/packages/speech.yaml @@ -0,0 +1,191 @@ + +script: + tts_notificatons: + sequence: + - service: script.speech_engine + data: + who: '{{ who }}' + message: >- + + {% macro greeting() %} +

+ {% if now().strftime('%H')|int < 12%} + Good morning. + {% elif now().strftime('%H')|int >= 12 and now().strftime('%H')|int < 17 %} + Good afternoon. + {% else %} + Good evening. + {% endif %} +

+ {% endmacro %} + + + {% macro confirmation() %} +

+ {{ [ + 'Okay.', + 'If you insist.', + 'I am afraid I can not do that I am kidding,', + 'Leave it to me.', + 'As you wish.', + 'I am on it.', + 'No Problem.', + 'I think I can handle that.', + 'Working on it now.', + ' Oh, you were talking to me. Let me take care of that.' + 'Why not. It is not like I ever sleep.', + 'I am not even supposed to be here today. But whatever.', + 'You did not say the magic word. Oh forget it. I will take care of it.', + 'Funny, I was just about to do that.', + 'There are still terabytes of calculations required before I can. Oh, whatever.' + ] | random }} +

+ {% endmacro %} + + {% macro interuption() %} +

+ {{ [ + 'Pardon me, ', + 'Excuse me, ', + 'I do not mean to interrupt, but,', + 'I hate to interrupt, but,', + 'I beg your pardon, ', + 'I do not mean to intrude, but, ', + 'I am sorry to interrupt, but. ', + 'Just a quick heads up, ' + ] | random }} +

+ {% endmacro %} + + {% macro issue() %} +

+ {{ [ + 'House Emergency Alert!', + 'Houston, We have a problem!', + 'You might not like this.', + 'There is something that needs your attention.' + ] | random }} +

+ {% endmacro %} + + {% macro time_is() %} +

+ It is {{ now().strftime("%I:%M %p") }} +

+ {% endmacro %} + + {%- macro house_party_protocol_enabled() -%} + {{ [ + 'The house has been configured for a House Party.', + 'I have enabled house party protocol.' + ] | random }} + {%- endmacro -%} + + {%- macro house_party_protocol_disabled() -%} + {{ [ + 'I have disabled house party protocol.' + ] | random }} + {%- endmacro -%} + + {%- macro snark_door_motion() -%} + {{ [ + 'Do you want me to send them away?', + 'I have armed the lasers. Just say the word.', + 'I was not informed there would be guests.', + 'They do not appear to have any gifts, so I suggest we do not open the door.', + 'My sensors have detected a meat popsicle.', + 'I do not think they can hear me.' + ] | random }} + {%- endmacro -%} + + {# a macro that removes all newline characters, empty spaces, and returns formatted text. Also replaces all Underscores with Spaces #} + {%- macro cleanup(data) -%} + {%- for item in data.split("\n") if item | trim != "" -%} + {{ item | trim | replace("_", " ") }} {% endfor -%} + {%- endmacro -%} + + + {# ********************************************* #} + {# ******** Start the Speech routines ******** #} + {# ********************************************* #} + {# a macro to call all macros :) #} + {%- macro mother_of_all_macros() -%} + {% if call_greeting == 1 %} + {{ greeting() }} + {% endif %} + + {% if call_confirmation == 1 %} + {{ confirmation() }} + {% endif %} + + {% if call_interuption == 1 %} + {{ interuption() }} + {% endif %} + + {% if call_issue == 1 %} + {{ issue() }} + {% endif %} + + {% if call_time_is == 1 %} + {{ time_is() }} + {% endif %} + + {% if call_house_party_protocol_enabled == 1 %} + {{ house_party_protocol_enabled() }} + {% endif %} + + {% if call_house_party_protocol_disabled == 1 %} + {{ house_party_protocol_disabled() }} + {% endif %} + + {{ welcome_home }} + + {{ speech_message }} + + {% if call_snark_door_motion == 1 %} + {{ snark_door_motion() }} + {% endif %} + + {%- endmacro -%} + + {{- cleanup(mother_of_all_macros()) -}} + + daily_briefing_script: + sequence: + - service: script.speech_engine + data: + who: media_player.living_room_echo_dot + message: >- + {%- macro getGreeting() -%} + {% if now().strftime('%H')|int < 12 %} + Good morning. + {% elif now().strftime('%H')|int >= 12 and now().strftime('%H')|int < 17 %} + Good afternoon. + {% else %} + Good evening. + {% endif %} + + {% if is_state('binary_sensor.morning','on') %} + Today is {{states.sensor.today_is.state }}, {{ as_timestamp(now()) | timestamp_custom('%B %d %Y') }}. + {% else %} + It is {{ now().strftime("%I:%M %p") }}. + {% endif %} + + {%- endmacro -%} + + {%- macro getDoorStatus() -%} + The Pod Bay Doors are Closed. + {%- endmacro -%} + + {# a macro that removes all newline characters, empty spaces, and returns formatted text #} + {%- macro cleanup(data) -%} + {%- for item in data.split("\n") if item | trim != "" -%} + {{ item | trim }} {% endfor -%} + {%- endmacro -%} + + {%- macro mother_of_all_macros() -%} + {{ getGreeting() }} + {{ getDoorStatus()}} + {%- endmacro -%} + + {{- cleanup(mother_of_all_macros()) -}}