Home Assistant (HA) can be easily controlled using the web interface of one of the mobile apps. However, there are more fun ways to communicate with your home. In this blog post I discuss talking (or chatting) to your home using a Telegram bot. I show how you can easily make a bot, connect it to Home Assistant and use AppDaemon to build a bot that can give you information on your home.
Best of all, using this setup you can communicate with your home even outside your local network without having to open up Home Assitant. So no port forwarding required! The Telegram bot acts as a sort of proxy between you and your HA instance.
Setting up a new Telegram bot
To start, we need to make a Telegram bot to link with HA. There is an extensive guide at the Telegram website. In essence it boils down to a few simple steps:
- Start a new conversation with the BotFather. This is a special bot that can be used to manage and create bots.
- Use the command
/newbot
to start the process of making a bot. - Fill in the name of your bot (this is the display name).
- Fill in the username of your bot (this has to be in the format of
<your_bot_name>bot
). - When all is done you will receive a HTTP API token from the BotFather. This is required to connect the bot to HA.
After creating your bot you can start chatting with it. Note that a user must always start a chat with a bot; a bot cannot start a conversation on its own.
Connecting a Telegram bot to Home Assistant
To start connecting our new Telegram bot to HA we need to enter our credentials for accessing the bot. We do this by adding a few lines to secrets.yaml
. If you do not want to use the secrets
file you can also skip this step and enter the credentials directly.
telegram_bot_key: <your api key from the BotFather>
telegram_bot_main_chat_id: <your chat id>
telegram_bot_chat_ids:
- <your chat id>
- <optional: other chat ids you want your bot to communicate with>
The chat id is the unique number that identifies your Telegram account. If you do not know your chat id you can send /getid
to one of the ‘id’-bots. For example the IDBot: http://telegram.me/myidbot. The list of chat ids is used to prevent other people talking to your bot.
The next step is to load the Telegram bot in HA. Do this by adding the following lines to your configuration.yaml
(or to a dedicated package file):
telegram_bot:
- platform: polling
api_key: !secret telegram_bot_key
allowed_chat_ids: !secret telegram_bot_chat_ids
I am using the polling method for the Telegram bot. Using this method you do not have to open up your Home Assistant instance to the outside world.
We can also link the bot to the Notify component of home assistant:
notify:
- name: telegram
platform: telegram
chat_id: !secret telegram_bot_main_chat_id
Basis of an AppDaemon Telegram app
AppDaemon is a great tool for building our Telegram bot as we can leverage the flexibility of Python. Alternatively, it is also possible to build your bot totally using yaml files, but that will take a bit more effort.
Start by adding a new instance to your apps.yaml
configuration for AppDaemon:
bot:
module: telegram
class: TelegramBot
Then create the associated python file (telegram.py
). To get started, copy the following to the file to use as wireframe:
import appdaemon.plugins.hass.hassapi as hass
class TelegramBot(hass.Hass):
def initialize(self):
# Start listening for Telegram updates
self.listen_event(self.receive_telegram_text, 'telegram_text')
def receive_telegram_text(self, event_id, payload_event, *args):
# Do something with the text
user_id = payload_event['user_id']
message = payload_event['text']
Save the file and the apps should automatically start. The app starts listening to telegram_text
events; these are triggered when the bot receives a message.
Saying Hi!
The first feature we can build in to the bot is to say a welcome message. However, it would be kind of annoyaing if the bot said “Hi” every time we send a new message to the bot. To remedy this I only send a greeting message at most once an hour.
Extend the initialize
function of the class to keep track of your conversations using a dictionary. We will store the last time a user sent a message in this dictionary.
def initialize(self):
self.time_between_conversations = 60 * 60
self.last_conversation = {}
A new function is added to the class that sends a greeting message. It checks whether the last message was sent longer than 60 minutes and, if so, sends a greeting message.
def greet_user_if_new_conversation(self, user_id, user_name):
"""Say hi when there is a new conversation"""
# For new users automatically set the time to zero.
if user_id not in self.last_conversation:
self.last_conversation[user_id] = 0
# Compute the time difference in seconds since the last message.
time_diff = time.time() - self.last_conversation[user_id]
if time_diff > self.time_between_conversations:
msg = f"Hi {user_name}"
# Send a message to the user.
self.call_service('telegram_bot/send_message',
target=user_id,
message=msg)
self.last_conversation[user_id] = time.time()
This new function is then called each time we receive a text:
def receive_telegram_text(self, event_id, payload_event, *args):
self.log(payload_event)
user_id = payload_event['user_id']
message = payload_event['text']
self.greet_user_if_new_conversation(user_id, payload_event['from_first'])
The from_first
payload variable should contain your first name (if set). Saying something to your bot should now result in a simple greeting:
Asking for the temperature
Now let’s do something usefull. I would like to keep track of the current temperature in my house. To facilitate this I created a small function that reports this. However, I only want my bot to tell me the temperature when I ask for it. So we need to do some (very simple) text parsing. I would like the bot to react to simple questions like:
Is it cold outside?
What is the temperature?
Is it warm at home?
This can be done with some very advanced artificial intelligence simple rules in python. The code below matches simple words in the input. Is it cold outside? matches due to cold and outside being present in the text.
if any((
'temperature' in message,
('warm' in message or 'cold' in message) and ('house' in message or 'inside' in message or 'outside' in message),
('warm' in message or 'cold' in message) and ('house' in message or 'inside' in message or 'outside' in message),
)):
# Report the temperature
self.send_house_temperature(user_id)
If the text message passed any of our rules we then send the temperature back:
def send_house_temperature(self, user_id):
"""Send information about the temperature in the house"""
sensors = {
'The outside temperature is {} °C.': 'sensor.temp_1', # Replace this with your sensor's entity id
'It is {} °C in the livingroom.': 'sensor.temp_2', # Replace this with your sensor's entity id
'The temperature of the livingroom is {} °C.': 'sensor.temp_2' # Replace this with your sensor's entity id
}
start_messages = [
'Let me see.',
'These are the temperatures currently.',
'I have read the sensors for you.'
]
msg = random.choice(start_messages)
# Read all sensors.
for template, sensor in sensors.items():
temp = self.get_state(sensor)
msg += ' ' + template.format(temp)
self.call_service('telegram_bot/send_message',
target=user_id,
message=msg)
In this new function I read out different sensors around my home. In this case measuring the outside temperature, and the temperature inside my livingroom and bedroom. A message is then constructed using a randomly chosen start sentence and the sensor readings.
Next steps?
This tutorial gave a quick overview of making a Telegram bot, connecting it to Home Assistant and using AppDaemon to send messages. The bot can easily be extended to send other messages or perform certain tasks within Home Assistant. Maybe you want to be able to control your lights using the bot, or activate the robot vacuum cleaner. Any cool ideas? Feel free to add them in the comments!
Full code (for reference)
import time
import random
import appdaemon.plugins.hass.hassapi as hass
class TelegramBot(hass.Hass):
def initialize(self):
# Start listening for Telegram updates
self.listen_event(self.receive_telegram_text, 'telegram_text')
self.time_between_conversations = 60 * 60
self.last_conversation = {}
def receive_telegram_text(self, event_id, payload_event, *args):
# Do something with the text
user_id = payload_event['user_id']
message = payload_event['text']
# Send greeting message.
self.greet_user_if_new_conversation(user_id, payload_event['from_first'])
if any((
'temperature' in message,
('warm' in message or 'cold' in message) and ('house' in message or 'inside' in message or 'outside' in message),
('warm' in message or 'cold' in message) and ('house' in message or 'inside' in message or 'outside' in message),
)):
# Report the temperature
self.send_house_temperature(user_id)
def greet_user_if_new_conversation(self, user_id, user_name):
"""Say hi when there is a new conversation"""
# For new users automatically set the time to zero.
if user_id not in self.last_conversation:
self.last_conversation[user_id] = 0
# Compute the time difference in seconds since the last message.
time_diff = time.time() - self.last_conversation[user_id]
if time_diff > self.time_between_conversations:
msg = f"Hi {user_name}"
# Send a message to the user.
self.call_service('telegram_bot/send_message',
target=user_id,
message=msg)
self.last_conversation[user_id] = time.time()
def send_house_temperature(self, user_id):
"""Send information about the temperature in the house"""
sensors = {
'The outside temperature is {} °C.': 'sensor.temp_1', # Replace this with your sensor's entity id
'It is {} °C in the livingroom.': 'sensor.temp_2', # Replace this with your sensor's entity id
'The temperature of the livingroom is {} °C.': 'sensor.temp_2' # Replace this with your sensor's entity id
}
start_messages = [
'Let me see.',
'These are the temperatures currently.',
'I have read the sensors for you.'
]
msg = random.choice(start_messages)
# Read all sensors.
for template, sensor in sensors.items():
temp = self.get_state(sensor)
msg += ' ' + template.format(temp)
self.call_service('telegram_bot/send_message',
target=user_id,
message=msg)
Series on Home Automation
This post is part of a series of posts on Home Automation. These posts usually cover a part of my own smart home or a project I worked on. I make heavy use of Home Assistant, Node-RED and AppDaemon to control my home; these posts are examples of this.
Interested in my setup?
Home Automation hardware setupOther posts in this series
Interested in Home Automation, Home Assistant or Node-RED? I have a few other posts that might be of interest:
Home Automation / Home Assistant setup with recommended hardware: The four-year update
Overview of my current hardware for my smart home powered by Home Assistant. An update on my previous post of four years ago (!) when I had just started with home automation.
Automatically turn on tv when streaming to a Chromecast
Quick Node-RED tutorial on automatically turning on a TV when streaming media.
Automatic dark mode for Home Assistant
Quick tutorial on setting up an automatic dark mode for Home Assistant.
Markus on
Hi,
i'm running Dr.Zzs "Holiday Lights" (NodeMCU, LED-Strip, controlled via HA) in a garden fence with my neighbour. My intention was to allow my neighbour to switch the fence light on and off and to change the colors. At the same time it was no option for me to open my HA instance to the internet to allow him any access...so, i decided to give telegram a try.
We ended up with a telegram chat group, which allows us to turn the fence light on and off and to switch colors. For a better usability i'm using the inline-keyboard in telegram which gives you clickable buttons for each control.
My solution is based on simple automations - sorry therefore, but i'm not familiar with coding ;-)
https://uploads.disquscdn.c... https://uploads.disquscdn.c... https://uploads.disquscdn.c...