Ever wanted to interact with your Home Assistant configuration when you’re not on the network? Want to run Home Assistant services and automations? The solution may be to create a telegram bot for Home Assistant.
A bot allows you to interact with your Home Assistant instance over a messaging platform. You can send custom commands to your bot to run automations, services and query different sensors in your setup. Today’s article goes through the installation and configuration steps to get a Telegram bot working in Home Assistant.
AppDaemon Installation
There are a couple different ways to create a telegram bot for Home Assistant. You can do it using purely YAML based Home Assistant automations and services. You could do it using something graphical like Node-Red. I chose to use AppDaemon for creating my bot. AppDaemon allows you to write Python-based applications that interact with Home Assistant. It extends your Home Assistant instance into the Python environment.
Why did I choose AppDaemon? As automations become more complex you may find yourself pulling your hair out while debugging complicated Home Assistant YAML files. AppDaemon lets you write those complex automations in Python making them easier to maintain and debug. Even if you haven’t written Python before you’ll be able to follow along and customize it for your needs. (Feel free to message me or comment too!)
Docker Image
I recommend using a docker image to get started using AppDaemon. You can use the official docker AppDaemon image, but that only works on x86 based architectures (so not a Raspberry Pi). Because I’m currently running my Home Assistant instance on a Raspberry Pi, I made a new docker image that works on the Raspberry Pi 3 with the latest version of AppDaemon. Check it out here.
I use docker compose to manage my containers for home automation. To add the AppDaemon image make sure you mount a volume for the configuration files and expose port 5050. Below you can see a snippet from my docker-compose.yml
file, you can see the full one in my GitHub repository.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
--- version: "3" services: homeassistant: image: homeassistant/raspberrypi3-homeassistant:0.76.2 volumes: - /home/pi/home-assistant-config/configuration:/config - /etc/localtime:/etc/localtime:ro network_mode: "host" ports: - "8123:8123" devices: - "/dev/ttyACM0:/dev/zwave:rmw" appdaemon: image: selfhostedhome/rpi-appdaemon:3.0.1 volumes: - /home/pi/home-assistant-config/appdaemon/conf:/conf - /etc/localtime:/etc/localtime:ro network_mode: "host" ports: - "5050:5050" environment: - HA_URL="http://localhost:8123" depends_on: - homeassistant |
Remember, only use my selfhostedhome/rpi-appdaemon
image if you’re running on a Raspberry Pi. If you’re wondering how to start a docker-compose file on startup, check out my article on Starting Docker Compose using systemd on Debian.
Config Files
So we need to make some configuration files to get AppDaemon playing nicely with Home Assistant and setup our Telegram bot. In the previous section I mentioned creating a conf
directory for AppDaemon. Create the following files in this layout within that conf directory:
1 2 3 4 5 6 7 |
. ├── appdaemon.yaml ├── apps │ ├── apps.yaml │ └── telegram_bot.py └── dashboards └── Hello.dash |
Let’s go through each of these files. First off is appdaemon.yml.
1 2 3 4 5 6 7 8 9 10 11 12 |
log: logfile: STDOUT errorfile: STDERR appdaemon: threads: 10 api_port: 5000 plugins: HASS: type: hass ha_url: "http://localhost:8123" hadashboard: dash_url: "http://localhost:5050" |
- Change the
ha_url
if your Home Assistant instance is running on a different host or port. Because AppDaemon is running on the same machine as Home Assistant for me I can just uselocalhost
. - The
dash_url
will be the address and port that the AppDaemon dashboard will show up on. We won’t be using this for our actual bot, but it is useful to check that AppDaemon is working correctly.
Next make the apps/apps.yaml
file.
1 2 3 4 |
telegram_bot: module: telegram_bot class: TelegramBotEventListener garage: cover.garage_door |
- The
module
here needs to match the name of the python file where the app will live. Ours will be in a file calledtelegram_bot.py
so we match it here. - The
class
attribute is the class within the Python module that will be used for the app. - My bot will interact with my garage, therefore I pass in my Home Assistant cover for my garage. The
garage
attribute will be an argument for my bot. There is some additional documentation here about this feature, but it basically makes it easy to access your Home Assistant sensors/covers/devices.
You can create the telegram_bot.py
file as well but leave it blank for now. We’ll be creating it in the next section.
Finally, create the Hello.dash
file. This adds a widget to our dashboard so that we can test that AppDaemon is working correctly.
1 2 3 4 5 6 7 8 9 10 11 |
title: Hello Panel widget_dimensions: [120, 120] widget_margins: [5, 5] columns: 8 label: widget_type: label text: Hello World layout: - label(2x2) |
Once all those files are created in your AppDaemon conf directory, restart the container. You should be able to access your AppDaemon dashboard on port 5050 of the machine running it. If you don’t see anything come up, check your docker logs for any errors. Feel free to comment or message me if something isn’t starting up correctly.
Home Assistant
There is nothing really special we need to do in Home Assistant for AppDaemon to work. What you do need to do though is create a Telegram Bot and register it with Home Assistant. Check out the Telegram section of my article on Home Assistant notification platforms to learn more about how to set it up.
Creating the Telegram Bot
Now that AppDaemon is up and running, it’s time to make our bot. For this article, I’m going to be making a bot that can tell us the status of our garage door and open/close it depending on the status. This is really handy if you don’t have your Home Assistant instance exposed on the internet and want to check on your garage door when away from home. If you want to create your own automated garage door check out my article about creating a DIY Smart Garage Door Opener.
The end goal will look something like this:
Initialization and Commands
Telegram considers any message that starts with “/” to be a command. Our telegram bot class checks the command sent and runs the appropriate function. All the following code should be in that telegram_bot.py
file located in your apps directory. The below code initializes the class and sets up command handling:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import appdaemon.plugins.hass.hassapi as hass class TelegramBotEventListener(hass.Hass): """Event listener for Telegram bot events.""" def initialize(self): """Listen to Telegram Bot events of interest.""" self.listen_event(self.receive_telegram_command, 'telegram_command') self.listen_event(self.receive_telegram_callback, 'telegram_callback') def garage_command(self, user_id): state = self.get_state(self.args["garage"]) msg = "The garage is currently {}".format(state) if state == "closed": keyboard = [[("Open", "/open_garage"), ("Do Nothing", "/do_nothing")]] else: keyboard = [[("Close", "/close_garage"), ("Do Nothing", "/do_nothing")]] self.call_service( 'telegram_bot/send_message', target=user_id, message=msg, disable_notification=True, inline_keyboard=keyboard) def receive_telegram_command(self, event_id, payload_event, *args): assert event_id == 'telegram_command' user_id = payload_event['user_id'] command = payload_event['command'] if command == "/garage": self.garage_command(user_id) |
Some interesting things to point out:
- We need to subclass the
hass.Hass
class to interface with Home Assistant. After inheriting from that class we define a method calledinitalize
to setup the class. - Callbacks are added to process receiving a command (basically a message starting with ‘/’) or receiving a callback message.
- The
receive_telegram_command
method determines the command that was sent and calls the appropriate function for the command. In this example, the bot just understands the/garage
command. - When the
/garage
command is sent thegarage_command
method is run. We can read the sate of the garage door using theget_state
method and passing in the argument used in the app configuration. - When calling the
telegram/send_message
method sets thekeyboard
attribute to give the user an interface to call different commands. Based on the status of the garage door different options are shown to the user.
Processing Callbacks
After the bot processes the initial command from the user it displays different follow-up actions. To process those actions we can use the telegram_callback
callback.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
def receive_telegram_callback(self, event_id, payload_event, *args): assert event_id == 'telegram_callback' data_callback = payload_event['data'] callback_id = payload_event['id'] if data_callback == '/open_garage': self.call_service( 'telegram_bot/answer_callback_query', message='Opening the garage!', callback_query_id=callback_id) self.call_service( 'cover/open_cover', entity_id=self.args["garage"]) elif data_callback == '/close_garage': self.call_service( 'telegram_bot/answer_callback_query', message='Closing the garage!', callback_query_id=callback_id) self.call_service( 'cover/close_cover', entity_id=self.args["garage"]) elif data_callback == '/do_nothing': self.call_service( 'telegram_bot/answer_callback_query', message='OK, you said no!', callback_query_id=callback_id) |
- The
data_callback
variable contains the option the user chose from the keyboard, we can check that variable to decide what to do. - If the user decides to open or close the garage we use the
telegram_bot/answer_callback_query
to respond to the user and thecover
services to open or close the services. - The arguments to the
call_service
method depend on the service being called. When interacting with the cover we pass in theentity_id
that the user passed in during app configuration. - For the
do_nothing
callback we don’t interact with the garage door.
Summary
You should now have a working telegram bot for Home Assistant! Telegram with AppDaemon and Home Assistant allow you to easily create a very flexible bot to interact with your home. What are some other commands to add to a bot? Using a different bot platform? Let me know in the comments!