diff --git a/static/img/telegram-1.jpg b/static/img/telegram-1.jpg new file mode 100644 index 0000000..eba1ff1 Binary files /dev/null and b/static/img/telegram-1.jpg differ diff --git a/static/img/telegram-2.png b/static/img/telegram-2.png new file mode 100644 index 0000000..90c5098 Binary files /dev/null and b/static/img/telegram-2.png differ diff --git a/static/img/telegram-3.png b/static/img/telegram-3.png new file mode 100644 index 0000000..c68c367 Binary files /dev/null and b/static/img/telegram-3.png differ diff --git a/static/img/telegram-4.png b/static/img/telegram-4.png new file mode 100644 index 0000000..dda5afd Binary files /dev/null and b/static/img/telegram-4.png differ diff --git a/static/pages/Build-a-bot-to-communicate-with-your-smart-home-over-Telegram.md b/static/pages/Build-a-bot-to-communicate-with-your-smart-home-over-Telegram.md new file mode 100644 index 0000000..da458d7 --- /dev/null +++ b/static/pages/Build-a-bot-to-communicate-with-your-smart-home-over-Telegram.md @@ -0,0 +1,302 @@ +[//]: # (title: Build a bot to communicate with your smart home over Telegram) +[//]: # (description: Integrate Telegram and Platypush to design chat-based automation flow.) +[//]: # (image: /img/telegram-1.jpg) +[//]: # (published: 2020-01-03) + +You’ve got your smart home fully set up. You regularly like to show off with your friends how cool it is to turn on +light bulbs, play videos and movies with a hint to your voice assistant, make coffee, and adjust the thermostat with a +tap on an app. Congratulations! + +But if you’re an automation enthusiast who rarely settles, you’ve probably grown frustrated with the number of apps +you’ll have to download and the number of interfaces you’ll have to master to control your gadgets. + +You’ll probably have an app for the lights, one for your media center, one for your smart shades, one for your +thermostat, and a Google Home app that zealously (and hopelessly) tries to put all of them in the same place. + +Probably, most of these apps won’t communicate with the others, and probably many of them won’t work if you aren’t on +the same network as your gadget. + +Wouldn’t it be cool if we could control everything from the same interface, without cluttering our phones or computers +with tons of apps, through an interface that is accessible both from mobile and desktop devices as well as through +external scripts/integrations, whether you are on your home network or outdoor? An interface that was both lightweight +and straightforward to use? + +But wait, hasn’t such an interface been around for a while, under the name of messaging or chat? After all, wouldn’t it +be cool to control our house, gadgets, and cloud services through the same interface that we use to send cat pictures to +our friends, and through a bot completely tailored to our needs, without all the boilerplate/frustration that usually +comes with third-party bots? + +## Chat-powered smart homes + +Enter the world of chatbot-powered smart homes. + +In this story, I’ll show you how to easily set up commands and routines on top of existing smart home installations. + +Many messaging apps and platforms exist out there, but so far the efforts of many of them (Facebook Messenger, +Whatsapp, Hangouts, etc.) in providing a usable developer’s API have been disappointing, to say the least. + +Gone are the golden days when everyone used XMPP or IRC as their messaging backbone and it was easy to integrate with +services that all spoke the same language: today’s messaging apps’ world is extremely fragmented. + +Moreover, as it’s in the interest of many of the big players to create walled gardens that don’t communicate with the +rest of the world, the most-used solutions out there don’t come with officially supported APIs/developer interfaces. + +Not only: some of the big players out there actively discourage users from using anything either than the official app +to interact with the +platform ([Whatsapp, I’m looking at you](https://news.softpedia.com/news/WhatsApp-Permanently-Bans-Users-of-Unofficial-Clients-475013.shtml)). + +In this extremely fragmented world made of several unconnected islands, Telegram represents a welcome exception. Their +[official bot API](https://core.telegram.org/bots/api) is well-documented and supported, and it’s very easy for anyone +who knows a bit of programming to build integrations. + +## Create the bot + +It’s quite easy to create a new bot on Telegram: + +- Open a conversation with the [BotFather](https://t.me/botfather). + +- Type `/start` followed by `/newbot` to create a new bot. Give your bot a display name and a username. + +- You’ll be provided with a link to start a conversation with your bot and a unique API key. Store it somewhere as we’ll + use it soon to configure the Platypush plugin. + +![BotFather interaction](../img/telegram-2.png) + +## Configuring your bot in Platypush + +- Install Platypush with the HTTP and Telegram extensions: + +```shell +pip install 'platypush[http,telegram]' +[sudo] apt-get install redis-server +[sudo] systemctl start redis +[sudo] systemctl enable redis +``` + +- Play a bit with it if you haven’t done so yet. Find a few things that you’d like to manage/automate — lights, music, + media, sensors, database, robots, smart plugs… — and install/configure the associated extensions. + +In this article, we’ll see how to configure our newly-created bot to control Philips Hue lights, music playback, and +PiCamera streaming. + +- Add the Telegram configuration to your `~/.config/platypush/config.yaml` file: + +```yaml +chat.telegram: + api_token: + +backend.chat.telegram: + enabled: true +``` + +The [backend](https://platypush.readthedocs.io/en/latest/platypush/backend/chat.telegram.html) enables you to receive +events (like new messages, attachments, requests, etc.) and create custom hooks on them. + +The [plugin](https://platypush.readthedocs.io/en/latest/platypush/plugins/chat.telegram.html) enables you to write to +chats, programmatically send messages and attachments, administer channels, etc. + +Let’s say that we want the bot to implement the following commands: + +- `/start`: Welcome the new user. +- `/help`: Show the available commands. +- `/lights_on`: Turn on the lights. +- `/lights_off`: Turn off the lights. +- `/music_play`: Play a music resource/URL. +- `/music_pause`: Toggle the playback pause state. +- `/music_next`: Play the next song. +- `/music_prev`: Play the previous song. +- `/start_streaming`: Start remote streaming on the PiCamera. +- `/stop_streaming`: Stop remote streaming on the PiCamera. + +All we have to do is to create event hooks in the Platypush `config.yaml`. In this context, you’ll need to: + +```shell +pip install 'platypush[hue,mpd,picamera]' +``` + +```yaml +# Hue lights configuration +light.hue: + # Hue bridge IP address + bridge: 192.168.1.10 + + # Default groups to control + groups: + - Living Room + +# MPD/Mopidy configuration +music.mpd: + host: localhost + port: 6600 + +# PiCamera configuration +camera.pi: + vflip: False + hflip: False +``` + +- Create a script (e.g. `~/.config/platypush/scripts/bot.py`) to handle the logic of your hooks: + +```python +from platypush.event.hook import hook +from platypush.utils import run + +from platypush.message.event.chat.telegram import CommandMessageEvent + +available_cmds = [ + '/lights_on', + '/lights_off', + '/music_play [resource]', + '/music_pause', + '/music_prev', + '/music_next', + '/start_streaming', + '/stop_streaming', +] + +# /start command handler +@hook(CommandMessageEvent, command='start') +def on_start_cmd(event, **context): + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Welcome! Type /help to see the available commands') + +# /help command handler +@hook(CommandMessageEvent, command='help') +def on_help_cmd(event, **context): + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Available commands:\n\n' + '\n'.join(available_cmds)) + +# /lights_on command handler +@hook(CommandMessageEvent, command='lights_on') +def on_lights_on_cmd(event, **context): + run('light.hue.on') + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Lights turned on') + +# /lights_off command handler +@hook(CommandMessageEvent, command='lights_off') +def on_lights_off_cmd(event, **context): + run('light.hue.off') + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Lights turned off') + +# /music_play command handler +@hook(CommandMessageEvent, command='music_play') +def on_music_play_cmd(event, **context): + if event.cmdargs: + run('music.mpd.play', resource=event.cmdargs[0]) + else: + run('music.mpd.play') + + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Playing music') + +# /music_pause command handler +@hook(CommandMessageEvent, command='music_pause') +def on_music_pause_cmd(event, **context): + run('music.mpd.pause') + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Music paused') + +# /music_prev command handler +@hook(CommandMessageEvent, command='music_prev') +def on_music_prev_cmd(event, **context): + run('music.mpd.previous') + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Playing previous track') + +# /music_next command handler +@hook(CommandMessageEvent, command='music_next') +def on_music_next_cmd(event, **context): + run('music.mpd.next') + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Playing next track') + +# /start_streaming command handler +@hook(CommandMessageEvent, command='start_streaming') +def on_start_streaming_cmd(event, **context): + run('camera.pi.start_streaming', listen_port=2222) + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Camera stream started - check it with vlc tcp/h264://hostname:2222') + +# /stop_streaming command handler +@hook(CommandMessageEvent, command='stop_streaming') +def on_stop_streaming_cmd(event, **context): + run('camera.pi.stop_streaming') + run('chat.telegram.send_message', chat_id=event.chat_id, + text='Camera stream stopped') +``` + +- Start Platypush: + +```shell +# Manual start +platypush + +# Service start +systemctl --user start platypush.service +``` + +- Open a conversation with your bot on Telegram through the link provided by the BotFather and start playing with it: + +![Bot interaction](../img/telegram-3.png) + +You can also invite the bot to a chat group if you want to share it with multiple users - now your friends can finally +easily mess the lights in your house! + +## Securing access + +Right now the bot is accessible by anyone — you probably don’t want that. You can configure the Telegram back end so it +only accepts messages from a specific list of chat IDs. (In Telegram, the chat_id is used both for private users and +groups). + +Send a message to the bot and open the Platypush logs or check its standard output: you should see some messages like +this: + +``` +2020-01-03 19:09:32,701| INFO|platypush|Received event: {"type": "event", "target": "turing", "origin": "turing", "id": "***", "args": {"type": "platypush.message.event.chat.telegram.CommandMessageEvent", "chat_id": your_chat_id, "message": {"text": "/help", ...}, "user": {"user_id": your_user_id, "username": "****", "is_bot": false, "link": "https://t.me/you", "language_code": "en", "first_name": "***", "last_name": "***"}, "command": "help", "cmdargs": []}} +``` + +Copy the `chat_id` associated with your user in the backend configuration: + +```yaml +backend.chat.telegram: + authorized_chat_ids: + - your_user_id +``` + +The bot will now reply with an error if you try to send a message from an unauthorized user. + +![Secured bot interaction](../img/telegram-4.png) + +## Conclusions + +We have only explored one specific feature of the Telegram integration in this article: the ability of the bot to react +to [`CommandMessageEvent`](https://platypush.readthedocs.io/en/latest/platypush/events/chat.telegram.html#platypush.message.event.chat.telegram.CommandMessageEvent) +events, run actions, and reply with text messages. + +As you can see from +the [list of supported Telegram events](https://platypush.readthedocs.io/en/latest/platypush/events/chat.telegram.html) +you can do more, such as: + +- Create hooks when someone shares contact info. Ever thought of letting a bot automatically store the new contacts sent + to you by your friends via chat? + +- Create hooks when you share a photo, video, or image file. For example, automatically download all media files sent to + a chat to your hard drive or a remote Dropbox folder. + +- Run actions on text messages instead of commands. You can use + the [`TextMessageEvent`](https://platypush.readthedocs.io/en/latest/platypush/events/chat.telegram.html#platypush.message.event.chat.telegram.TextMessageEvent), + for example, if you prefer to type “turn on the lights” instead of `/lights_on`. + +- Take a picture from the camera and send it to yourself through + the [`send_photo`](https://platypush.readthedocs.io/en/latest/platypush/events/chat.telegram.html#platypush.message.event.chat.telegram.TextMessageEvent) + action. + +- Automatically moderate chat groups through + the [`chat.telegram`](https://platypush.readthedocs.io/en/latest/platypush/plugins/chat.telegram.html) actions. + +- You can also deploy multiple bots, e.g. per device, so you can run actions on a specific device from the associated + chat, or instead, use a single bot as entry point and deliver messages to other devices over MQTT, Kafka, or HTTP API. + +As long as there’s a plugin for it, you can now do it through your chat bot.