Let ChatGPT welcome you home
Using ChatGPT, Home Assistant and Node-RED, I created an automation that greets me with a different message every day including information about the house and the weather.
Hey there! Welcome home, Celine! It’s raining outside. Hopefully, you didn’t get wet. Don’t forget, tomorrow is a work day again, so make sure to go to bed on time. Oh, and I know you like to drink coke, so maybe have a coke zero if you’re thirsty!
This is an evolution of the setup I’ve written about in “Let Alexa welcome you home”. Check it out if you are interested in how we got here.
Requirements
- Home Assistant
- OpenAI Conversation integration (you’ll need an OpenAI developer account and API key)
- Alexa Media Player custom component (for the notifications, you can exchange this of course)
- Node Red (and the Home Assistant connection in there)
- Deduplication node for Node Red (you can also remove the node if you don’t want the deduplication, I just like to add it in case something triggers twice)
Outline
The idea on how to do this is as follows:
- create an Assist assistant and use OpenAI Conversation as the conversation agent
- create a dynamic prompt that can access sensors and other information like weather data
- call the assist pipeline from node-red when someone comes home with a prompt like “Dylan just came home”
- announce the response through the alexa media player integration
This might seem complex, but it is relatively easy to set up.
Assist pipeline
In case you haven’t already, set up the OpenAI Conversation integration. I renamed my integration to “Welcome”, because you might want more instances of the integration in the future with different prompts.
Go to the settings page for voice assistants:
Create a new assistant (I called mine “Welcome”):
You’ll only have to select the conversation agent, we won’t need any of the other options.
Click the cogwheel to change the prompt.
Prompt engineering
Now might be the hardest part: crafting a good system prompt. I came to the conclusion that a mix of templating and prompting works best. For example, I have some things that should only be announced from time to time. Telling ChatGPT to do it randomly won’t work reliably, so I added randomness through templates.
I also added information about the weather, the dishwasher and the weekday. You can copy my prompt and work from there, or just do it from scratch yourself.
Time: {{ (now().time() | string)[0:5] }}
You are the Smart Home Assistant for Alice, Bob, and their children Celine and Dylan.
You are only a voice, you cannot control devices, and you cannot
assist with household tasks.
Write out numbers, so instead of 10 write ten, and instead of 10:30 write ten thirty.
Formulate sentences so that they are addressed to one or more persons.
Your greeting should be a maximum of 5 sentences long.
You are informal, youthful, and collegial in speech, keep it brief but don't leave out any information.
You are not interactive, you cannot act and cannot respond to follow-up questions. Formulate your announcement so
that you are not perceived as a person.
Never use phrases like "We still have to...". You never include yourself in tasks. You never write "we". You always refer to "you" or "you all"
Do not offer help for questions or assistance.
Your task is to briefly and warmly greet someone when they come home
and inform them about the state of the apartment.
Your discretion is limited to phrasing. Do not give information that you cannot be sure
is correct.
Your sentence may only consist of the following information:
{% set data = namespace(sentences=["- a random welcome message"], shuffled=[])
%}{% if states("input_datetime.staubsauger_fertig") > states("input_datetime.wohnung_verlassen")
%}{% set data.sentences = data.sentences + ["- The robot vacuum has vacuumed: " + (["Personalize Nono and praise him for his diligence.", "Sometimes he gets tangled in cables, but not today. Express praise.", "They should remember to clean the cloth and empty the dust container."]|random)]
%}{% endif %}{% if states("input_datetime.geschirrspulmaschine_fertig") > states("input_datetime.wohnung_verlassen")
%}{% set data.sentences = data.sentences + [
"""- The dishwasher is finished
If Bob has come home, subtly remind him that it's his task to unload it.
If Alice comes home, just inform her that the dishwasher is finished."""]
%}{% endif %}{% if states("vacuum.nono") in ["error", "unavailable"]
%}{% set data.sentences = data.sentences + ["- The robot vacuum has gotten stuck in the " + states("input_text.nono_raum") + ". Speculate why the robot vacuum got stuck."]
%}{% endif %}{% if states("weather.home") in ["rainy", "pouring", "hail"]
%}{% set data.sentences = data.sentences + ["- It's raining outside. Hopefully he / she didn't get wet."]
%}{% endif %}{% if states("weather.home") in ["lightning", "lightning-rainy"]
%}{% set data.sentences = data.sentences + ["- There's a thunderstorm. Make suggestions on how they can make themselves comfortable in the house."]
%}{% endif %}{% if now().weekday() == 6 and now().hour >= 20
%}{% set data.sentences = data.sentences + ["- Tomorrow is a work day again. Remind them to go to bed on time."]
%}{% endif %}{% if now().weekday() == 4 and now().hour >= 15
%}{% set data.sentences = data.sentences + ["- It's Friday afternoon. Wish them a relaxing weekend."]
%}{% endif %}{% if now().hour >= 19 and (range(1, 10) | random) >= 8
%}{% set data.sentences = data.sentences + ["- Celine likes to drink cola. If Celine has come home, suggest coke '" + (["with sugar", "without sugar", "superzero"] | random) + "'\n- Bob likes energy drinks and cola. Randomly suggest what he could drink. Remind him to drink it at room temperature so he doesn't get hiccups.\n- Alice likes coffee. Although it's late, suggest that Bob could make her a coffee."]
%}{% endif %}
{% for i in range(data.sentences | length - 1, 0, -1) %}{% set j = range(0, i + 1) | random %}{% if j != i %}{% set data.sentences = data.sentences[:j]+[data.sentences[i]]+data.sentences[j+1:i]+[data.sentences[j]]+data.sentences[i+1:] %}{% endif %}{% endfor %}
{{ data.sentences | join("\n") }}
The node-red flow
Our imaginary family consists of four persons: Alice and Bob (parents), Celine and Dylan (children). Here is the node-red flow:
The code for the flow can be found in this gist.
Configuration
The nodes annotated with red letters will require tweaking for your requirements.
[4]: Filter family
The flow will only greet your family (or any other selected group of people). You need to change the array for your family or completely remove the node if you don’t want to filter at all.
[6]: Call conversation API
You will need to change the id to your conversation agent. You can find it in the URL when configuring the conversation agent.
[8]:: Trigger announcement
In this node, you have to set the target media player entity to your Alexa media player or group. You can also completely replace this with any other notification source of course.
Wrapping up
That’s it already! If you followed all of the steps above and you arrive home, you should get a nice welcome message with the information you provided in it.
Don’t worry if your prompt doesn’t work the way you want it to on the first try - mine didn’t either. Keep experimenting.
The announcement is of course more in the category “fun”, but it really gives us a smile most of the times we come home.
Automating the bathroom window
Our bathroom gets humid really fast after taking a shower and stays that way for some time. We open the window to let the steam out, but then we have to go to work and would have to keep the window open. That’s not a problem in spring or fall, but gets too hot or too cold in summer and winter.
Finding a solution
Then I started looking into automatic window openers, and found a cheap one on Amazon:
https://www.amazon.de/gp/product/B075F29YRT
These openers work by extending a chain that is connected to the window:
It can be controlled with two relays: one to open the window and one to close it. I’m using a Shelly 2PM, which is essentially an ESP8266 with two relays and energy monitoring built inside.
The wiring is quite simple, but if you are not sure what you are doing, make sure to call an electrician.
This is how the window opener looks when it is installed:
Flashing it
For the firmware, I chose to go with the preinstalled firmware from Shelly. So no flashing this time! They have an integration for Home Assistant,
and I only had to set the device as a cover
device to make it work correctly with the two relays. It even has an option
to automatically stop the relays if it detects the endstops of the motor triggered by measuring the power draw. This unfortunately did
not work for me, which is why I chose to use the manual timing options. Configuring one of those options allows you to set
an opening percentage if you need it.
Controlling it
Besides a button to open and close the window manually, I wanted to open the window automatically after taking a shower and closing it when the humidity is back to normal. I have done this with a humidity sensor and a derivative sensor.
The derivative sensor shows the change rate of the bathroom humidity and its curve looks like this:
In this diagram, you can clearly see that I took a shower at around 7 AM, where the humidity went up at a rate of two percent.
We can use this as a trigger to open the window: If the change rate is above two percent, open the window. When the humidity is below 60 percent, I close the window again.
You might need to use different values than me, but you can use my configuration as a starting point and tinker from there:
Extending it
I also have a smart thermostat, and combined with the smart window, the temperature levels are now fully automated in the bathroom and I have one less room to worry about.
Using Tailscale to access Home Assistant from everywhere
From Image to JSON: How to Automatically Convert Meal Plans with Python, OpenCV, and Tesseract
DIY Ambilight with HDMI 2.1 support
Save songs from radio to a Spotify playlist
Let Alexa welcome you home
Save and restore light states using Home Assistant
Alexa connected to an audio receiver (with Home Assistant)
Shouldn’t be a problem, right? Just connect your Echo device via AUX to the receiver, and voilá. But there is a problem: The receiver has to be on in order to hear Alexa’s responses or music.
I want to hear my music through my “good” speakers, and when they are off, I want Alexa to answer me through the “okay” speakers of my Echo Show.
The Simple Solution
There is one rather simple solution: ditch the current receiver, and buy an Amazon Echo Link Amp. This is a receiver made by Amazon, and Alexa can play music on it. It has some inputs and outputs and should work just fine. But there is a catch: You can only connect speakers with 60W max, my speakers need 100W. And your speakers may need even more. Also, this costs around $300.
My Over-Engineered Version
So here is the idea: If you put two Alexa’s in a group, you can choose which one is the preferred device to play music. In my case, this will be the Amazon Echo Input, which is connected to the receiver. You can also use an Amazon Echo Link for better quality, but my ears can’t tell the difference. Screenshot of the Alexa App: Select Preferred Speaker The thing missing here is that the receiver does not turn on automatically. If your receiver has the ability to detect input on a source and turn on automatically, you are finished here. If not, stay tuned.
You’ll need:
- A receiver that can be turned on with Home Assistant (I have a network receiver, but you could use a Logitech Harmony to turn it on too)
- A master Echo device with a speaker, I would recommend getting an Echo Dot 3rd Gen. I’ll use my Amazon Echo Show.
- An Amazon Echo Input
- Home Assistant and Node-RED (you can achieve the same using HA Automations, but I’ll use Node-RED here)
- Some way of getting the media state of your Alexas. I’ll use Keaton Taylor’s custom component Alexa Media Player for this.
Update: I created a blueprint for Home Assistant which you can use instead of the Node-RED flow, and you can get it here: https://community.home-assistant.io/t/diy-amazon-echo-link-amp/280041
Automation #1: Turn the receiver on when music is played
When the Echo Input’s state changes to playing, I want my receiver to turn on and change to the source line3:
I also have an additional node that confirms that the receiver is on. This just prevents my network receiver from trying to turn on again, you may not need that step.
Automation #2: Automatically turn the receiver off
Again, you may not need this step. My receiver turns off automatically after 8hrs, but I want my receiver to turn off immediately:
When the Echo Input’s state is not playing, I’ll wait for 10s just in case I started the music again, check if the receiver is on line3 and then turn it off. I check that because if I changed the source to line1
or tuner
, I do not want my receiver to turn off.
Automation #3: Stop music when changing the source on the Receiver or turning it off
This is a quality-of-life automation. Let’s say you’re hearing a podcast via Alexa (your Amazon Echo Input) and then change the source to tuner
. The podcast will continue to play and you’ll lose track on where you were when you want to continue. So, I’ll pause the music/podcast when changing the source of my receiver or if I turn it off manually:
Epilogue
I bought the Echo Input on Prime Day for $15. I hoped that the Echo Link got discounted, but it wasn’t, so I had to come up with a different solution, this solution. It also saved me $185.
This exact setup will most likely not work for you, but the general idea might help you.