Найти в Дзене

Статья 7. Telegram-бот с несколькими чатами: алерты — в группу, управление — в личку. + Бонус - добавим меню для управления

Очередное обновление вносит изменения в интеграцию telegram bot, использованный ранее target перестанет поддерживаться в сентябре, вместо него используется chat_id. Статья в целом сохраняет актуальность, но с учетом изменений ниже. К сожалению, не самое продуманное изменение и оно не позволяет указать в интерфейсе {{ trigger.event.data.chat_id }}, т. е. ответ в тот же чат из которого пришел запрос, система предлагает выбрать конкретный чат, но нам это не нужно. Заходим в текстовый редактор. Если в тексте есть строка: target: "{{ trigger.event.data.chat_id }}" Заменяем на: chat_id: "{{ trigger.event.data.chat_id }}" Если такой строки нет, добавляем ее вручную: Когда вы создаёте Telegram-бота для умной фермы с одним чатом рано или поздно возникнут проблемы: Проблема 1: Информационный шум: Проблема 2: Безопасность доступа Проблема 3: Удобство использования Решение уже придумано и называется "Принцип наименьших привилегий", т. е. каждый пользователь (в данном случае в качестве пользовател
Оглавление

UPD 1:

Очередное обновление вносит изменения в интеграцию telegram bot, использованный ранее target перестанет поддерживаться в сентябре, вместо него используется chat_id. Статья в целом сохраняет актуальность, но с учетом изменений ниже.

К сожалению, не самое продуманное изменение и оно не позволяет указать в интерфейсе {{ trigger.event.data.chat_id }}, т. е. ответ в тот же чат из которого пришел запрос, система предлагает выбрать конкретный чат, но нам это не нужно.

-2

Заходим в текстовый редактор.

-3

Если в тексте есть строка:

target: "{{ trigger.event.data.chat_id }}"

Заменяем на:

chat_id: "{{ trigger.event.data.chat_id }}"

Если такой строки нет, добавляем ее вручную:

-4

Часть 1: Зачем разделять чаты?

Когда вы создаёте Telegram-бота для умной фермы с одним чатом рано или поздно возникнут проблемы:

Проблема 1: Информационный шум:

  • перемешаны команды и уведомления - если произошла авария и уведомлений сыпется много, то вы врятли сможете адекватно управлять через этой же чат;
  • если чат групповой - важные аварийные сообщения "теряются" среди десятка ручных запросов - как следствие все перестают на него реагировать, так как "срабатывания" (уведомления) ложиные и это не проблема, а кто-то отправил команду.

Проблема 2: Безопасность доступа

  • в группе могут быть люди, которым не нужно управлять оборудованием, но доступ к уведомлениям у них должен быть, напоминаю, что доступ к командам предоставляется чату, а не конкретным людям в нем;
  • сложно отследить, кто и когда выполнял критические действия и выполнялись ли они вообще.

Проблема 3: Удобство использования

  • в групповом чате сложно организовать интерактивные меню - например, меню может быть каскадным, т. е. с начала вы выбираете, что хотите узнать температуру, а затем выбираете в каком бассейне. Может получиться так, что кто-то дошел до меню с выбором бассейна, но его выбирать не стал, все остальные видят, что необходимо выбрать бассейн, но не знают какой это пункт меню - узнать температуру? добавить подменной воды? покормить? А еще этим меню может захотеть воспользоваться несколько человек одновременно. В общем вы поняли;
  • невозможно настроить персональные настройки уведомлений и ограничения доступных действий.

Часть 2: Как разделять чаты правильно?

Решение уже придумано и называется "Принцип наименьших привилегий", т. е. каждый пользователь (в данном случае в качестве пользователя у нас конкретный чат) должны иметь ровно столько прав, сколько необходимо для их задач. Задачи же можно разделить на 3 уровня (минутка плача - на сколько же яндексу не интересен дзен, редактор статей на уровне блокнота, невозможно даже вставить таблицу, поэтому заранее извиняюсь, я бы сделал удобно и понятно, но тут это просто невозможно):

Уровень 1: Мониторинг - Групповой чат - Общие алерты, важные события - Падение температуры, отключение датчика

Уровень 2: Управление - Личные чаты - Индивидуальные команды, запросы данных - /temp, /photo

Уровень 3: Администрирование - Приватный чат владельца - Критические действия, настройка системы, управление персоналом - включение/выключение устройств, оповещение о присутствии/отсутствии персонала

Первые два уровня рассмотрим в этой статье, третий уровень позже, когда создадим прифили для всех сотрудников и научим умный дом определять присутствие (логика простая и надежная - если телефон подключился к wi-fi, то его владелец пришел на ферму, отключился от wi-fi ушел с фермы).

Часть 3: Создаем групповой чат, добавляем бота и прописываем в HA

  1. Открываем Telegram и нажимаем "Новое сообщение" → "Новая группа";
  2. Добавляем бота и других участников кто также будет следить за оповещениями;
  3. Придумываем имя группы (добавьте в название "alarm", "alert", "оповещения" или что-то аналогичное), добавляем яркую картинку, кажется не значительным, но заметно упрощает поиск среди других чатов, что экономит время;
  4. Делаем бота админом;
  5. В телеграмме групповые чаты создаются всегда (или почти всегда) с коротким id, но при достижении чатом какого-то размера, его id изменяется, чтобы не попасть в ситуацию когда ваш чат работал год, а потом внезапно перестал, потому что у него изменился id и Home Assistant теперь считает его недоверенным, выполняем следующие действия:
    - заходим в редактирование группы;
    - изменяем тип группы на публичный, задаем любую ссылку (она не будет использоваться) и сохраняем;
    - снова изменяем тип группы на приватный и сохраняем;
-5
-6

6. Теперь в чате с группой ссылка будет выглядь так https://web.telegram.org/a/#-1001234567890. Если в адресе у вас нет -100 и вместо выделенной буквы "а" стоит "k", то адрес группы закешировался старый и для получения актуального можно удалить кеш телеграм, перезайти, открыть телеграм в инкогнито, в другом браузере или всё вместе.

7. Добавляем id чата в разрешенные в HA. Настройки - Устройства и службы - Telegram bot - Добавить разрешенный ID чата - вставляем ID скопировав его из адресной строки (формат "-1001234567890").

8. Ищем все автоматизации с оповещениями и добавляем в цель id нашего группового чата:

-7

Часть 4: Настраиваем ответ в тот же чат из которого пришел запрос

Проблема в том, что если не указывать "Цель", то бот будет отправлять ответ в первый чат, независимо от того из какого чата поступила команда, но и прописать конкретный id чата мы не можем, запрос же можем прийти из любого и ответить нужно именно в него.

Во всех автоматизациях, где триггер (блок Когда) - telegram_command, указываем в "Цели" -

{{ trigger.event.data.chat_id }}
-8

Часть 5: Ограничение для чатов по доступным запросам

Ограничения добавляем в автоматизации в блок "И если (необязательно)"

-9

Варианты ограничений:

  • только личные чаты (у групповых id всегда отрицательный):
{{ trigger.event.data.chat_id > 0 }}

только конкретные чаты:

{{ trigger.event.data.chat_id in [-1001234567890, 412345678] }}
-10

Простые команды на запрос текущих показателей убирать из группового чата не рекомендую. Может возникнуть ситуация, когда кто-то обнаружил проблему и вызвав команду в общем чате он может уведомить о ней всех.

Часть 6: Клавиатуры для удобной отправки запросов

Умный дом разрастается, количество команд для управления растет и все их нужно запоминать? Записывать? А если очень нужно, но забыл и никуда не записывал? Есть красивое удобное и простое решение - пользовательская клавиатура в чате телеграм.

Есть два вида клавиатур и мы рассмотрим их оба. Обычная клавиатура проще, встроенная интереснее. Поддерживать обе выглядит избыточным - сколько и какие клавиатуры делать выбор за вами, я буду поддерживать обе.

Вариант 1. Обычная клавиатура

Описывать как работает не буду, проще сделать и сразу станет понятно.

  1. Создаем автоматизацию, добавляем "Когда" - telegram_command - command: /start;
  2. В "Тогда" - Действия - Telegram bot - Отправить сообщение
  3. Заполняем:
  • Идентификатор записи конфигурации - интеграция с ботом
  • Сообщение - вставляем "Выберите действие:" (без кавычек, отправить обычную клавиатуру без сообщения нельзя, поэтому поле оставить пустым не получится)
  • Цель - {{ trigger.event.data.chat_id }}
  • Клавиатура:
    /temp, /photo
    /photo, /temp
    /start
-11

Команды задублированы для наглядности - кнопки в отдной строке вводятся через запятую, чтобы отображались на разных строках, необходимо на новой строке и вносить.

В веб-версии, клавиатура спрятана под кнопкой:

-12

В приложении на телефоне заменяет обычную клавиатуру. Если кликнуть на поле для ввода текста отобразится стандартный йцукенг:

-13

4. Нажимая на кнопки текст с кнопок отправляется в чат и обрабатывается соответствующей интеграцией

5. Если кнопок становится много - делаем многоуровневую клавиартуру. Например, /start вам дает возможность выбрать /получить_данные, /управление_устройствами. /получить_данные - выводит список доступных команд - /temp, /co2 и т. д., которые уже показания и возвращают.

Вариант 2. Встроенная клавиатура (inline_keyboard)

1. Повторяем Вариант 1, но "command: /menu", сообщение оставляем пустым, а в поле с клавиатурой добавляем (редактор адовый в дзене, все отступы при копировании съедает, проверяйте при копировании, где три "-" отступов быть не должно, где два "-" два пробела, где один "-" четыре пробела):

- - - 🌡️ Температура
- /temp
- - 🧪 co2
- /co2
- - - 📊 График за сутки
- /graph
- - 📷 Фото камеры
- /photo
- - - 🔔 Меню
- /menu
-14

Читать так:

  • если в первом столбце тире - это перенос строки в меню
  • если во втором столбце тире - такой текст будет отображаться на кнопке
  • если тире только одно в третьем стобце - при нажатии на кнопку отправляться в умный дом будет именна эта команда

Т. е. у встроенной клавиатуры можно сделать красивый текст на кнопке, а отправлять понятные умному дому команды.

-15

2. Вы же уже нажали? И ничего не произошло? Так и должно быть, отправляются скрытые сообщения, которые в чате не отображаются, не засоряют его и обрабатывать их нужно по другому.

3. Создаем дубль автоматизации /temp:

-16

4. Меняем в "Когда" - Тип события telegram_callback - Данные события - data: /temp

-17

5. В "Тогда" добавляем действие - Действия - Telegram bot - Ответить на запрос обратного вызова

-18

6. Идентификатор записи конфигурации - интеграция с ботом, Сообщение - Запрос принят, идет обработка..., Идентификатор обратного вызова - {{ trigger.event.data.id }}

-19

7. Хватаем за "=" и меняем действия местами, первым должен стать ответ на запрос обратного вызова

-20

8. Не забываем проделать теже манипуляции с /photo

9. Всё - встроенная клавиатура работает

Часть 7: Итоги

Что мы сделали за эту статью:

  • Создали интерактивное меню двух видов с обычной и встроенной клавиатурой
  • Настроили ответы на запросы пользователей в меню
  • Настроили безопасность - разграничение прав для чатов
  • Разделили потоки уведомлений - алерты идут в групповой чат, команды принимаются из личных

Часть 7: Анонс: Следующие статьи — расширяем парк датчиков и визуализацию

Пока со следующей статьей не определился, будет что-то из описанного ниже.

Красивые дашборды для визуализации - создадим панель управления с:

  • Графиками температуры в реальном времени
  • Картой фермы с расположением датчиков
  • Цветовой индикацией состояний
  • Мобильной версией для телефона
  • Трендами и прогнозами

Новые датчики для контроля уровня воды в бассейнах:

  • Емкостной датчик уровня воды - бесконтактное определение уровня в бассейнах/трубах
  • Ультразвуковой дальномер - точное измерение расстояния до воды, т. е. уровень, но не просто наличие и отсутствие как у емкостного, а точный в сантиметрах
  • Лазерный дальномер - еще один вариант для тестирования и отпределения оптимального

Диагностика оборудования (вибрация, ток):

  • Датчик вибрации - контроль работы насосов и двигателей
  • Датчик тока (неинвазивный) - мониторинг потребления оборудования

Управление мощностями:

  • Твёрдотельное реле - управление нагрузкой
  • Контактор + стартер - управление мощными двигателями (с большими пусковыми токами, которые реле со временем расплавят)