openHAB and Telegram Bot
openHAB 2 comes with a Telegram binding which allows to run a Telgram Bot. This bot can both send messages to users and groups, and can receive commands and respond to them. That's useful: your home automation system can send all kind of details to your mobile phone.
For this to make it work it needs a couple things:
First of all a mobile phone with the Telegram app on it. You can either have the bot message you directly, but this only works for one person. Or you create a group, and have the bot send the messages to the group instead. Find out about the group ID here.
Then you need to create a Telegram Bot. Instructions are available here.
And everything needs to be hooked up in openHAB.
Let's start with installing the Telegram binding. As usual I use Ansible to install and deploy everything, instructions are available in some of these blog postings.
- name: Get list of available and installed extensions
uri:
url: "http://{{ ansible_host }}:8080/rest/extensions"
register: oh2_extensions
changed_when: false
- name: Install extensions
uri:
url: "http://{{ ansible_host }}:8080/rest/extensions/{{ item }}/install"
method: POST
when: "not (oh2_extensions.json|byattr('id', item))[0].installed"
with_items:
- binding-telegram
register: oh2_install_extensions
Store the Bot Token in a text file (it's "credentials/telegram-bot.txt" in my case). Make sure only your user can read the file - anyone with access to the Token can control the bot. (chmod 0600 or 0660).
Things
I use a couple different Telegram groups:
- One for the family, the bot is sending important messages there
- One for more detailed messages I'm interested in (kind of a debugging channel)
- A testing channel which I use to try out new features
The (negative) channel ids are stored in text files. The ids are loaded by Ansible when I deploy the "telegram.things" file:
Thing telegram:telegramBot:HA_Bot [ chatIds="{{ lookup('file', playbook_dir + '/credentials/telegram-ha-channel.txt') }}","{{ lookup('file', playbook_dir + '/credentials/telegram-ha-test-channel.txt') }}","{{ lookup('file', playbook_dir + '/credentials/telegram-ha-details-channel.txt') }}", botToken="{{ lookup('file', playbook_dir + '/credentials/telegram-bot.txt') }}", parseMode="Markdown" ]
Looks a bit long, because of the many Ansible Lookups. The deployed file in "/etc/openhab2/things/telegram.things" is much shorter:
Thing telegram:telegramBot:HA_Bot [ chatIds="-<channel main>","-<channel details>","-<channel test>", botToken="<token>", parseMode="Markdown" ]
Note: "HA_Bot" is the name of this bot. This name is required for all other activities with this bot.
Items
The Binding provides a couple channels, I'm mostly interested in:
- "lastMessageText": the last command sent by someone
- "lastMessageDate": the time someone sent the last command
- "chatId": the group or private chat someone sent a command to - the bot needs to reply to that
All channels defined as Items:
String telegramLastMessage "Telegram Bot Last Message" { channel = "telegram:telegramBot:HA_Bot:lastMessageText" }
String telegramLastMessageURL "Telegram Bot Last Message URL" { channel = "telegram:telegramBot:HA_Bot:lastMessageURL" }
DateTime telegramlastMessageDate "Telegram Bot Last Message Date" { channel = "telegram:telegramBot:HA_Bot:lastMessageDate" }
String telegramLastMessageName "Telegram Bot Last Message Sender" { channel = "telegram:telegramBot:HA_Bot:lastMessageName" }
String telegramLastMessageUsername "Telegram Bot Last Message Username" { channel = "telegram:telegramBot:HA_Bot:lastMessageUsername" }
String telegramLastMessageChatId "Telegram Bot Last Message chatId" { channel = "telegram:telegramBot:HA_Bot:chatId" }
String telegramLastMessageReplyId "Telegram Bot Last Message replyId" { channel = "telegram:telegramBot:HA_Bot:replyId" }
Rules
Once the bot is running, it can send messages on it's own:
val telegramAction = getActions("telegram","telegram:telegramBot:HA_Bot")
telegramAction.sendTelegram(Long::parseLong(TELEGRAM_CHANNEL_HA_DETAILS), "%s %s", "Telegram Bot", "online")
This will send a test message to the Telegram group defined in TELEGRAM_CHANNEL_HA_DETAILS.
For responding to messages, the bot needs to be triggered by an event. It's not useful to work on "lastMessageText", because a user can send the same message multiple times - in this case no change event is triggered. An update is triggered, but that's not helpful here. However with every message the "lastMessageDate" will change, and that can be used for a trigger:
rule "Telegram Bot receive test"
when
Item telegramlastMessageDate received update
then
if (telegramLastMessage.state.toString == "/test") {
logInfo("Telegram Query Test", "Test")
val telegramAction = getActions("telegram","telegram:telegramBot:HA_Bot")
telegramAction.sendTelegram(Long::parseLong(telegramLastMessageChatId.state.toString), "Test received")
}
end
This example picks up a "/test" command, and sends a simple message back.
Comments
Display comments as Linear | Threaded