Запускаем Telegram Bot на панеле оператора (HMI) от Weintek

от автора

Возможно ли в промышленной панеле оператора (HMI) создать своего Телеграм бота?

В HMI от Weintek это реализуемо! В данном туториале мы научим нашу панельку работать с Telegram Bot API, напишем Echo-бот и реализуем отправку сообщений по событию.

Когда появляется необходимость удаленного контроля за работой автоматизированной системы, например опрос показаний с каких-либо внешних датчиков по запросу или в случае аварии получение уведомлений — в таких ситуациях, возможно, пригодится дружба Telegram c HMI от Weintek.

Создание проектов для оборудования от Weintek осуществляется в среде разработки EasyBuilder Pro (далее EB Pro). Начиная с версии EB Pro V6.05.01 появилась возможность писать скрипты на JavaScript по стандарту ECMAScript 2017, правда данная опция присутствует пока в стандартных и расширенных моделях cMT серии X. Скачать самую свежую версию EB Pro можно тут.

Для начала нам необходимо создать проект в EB Pro, выбрать вашу модель HMI, в моем случае это cMT2078X.

Файл -> Новый -> cMT2078X -> OK» title=»Файл -> Новый -> cMT2078X -> OK» width=»920″ height=»591″ data-src=»https://habrastorage.org/getpro/habr/upload_files/e36/d19/987/e36d199871272bc116c2cb0434d69c97.jpg» data-blurred=»true»/><figcaption>Файл -> Новый -> cMT2078X -> OK</figcaption></figure>
<p>После добавления “<em>Объект JS</em>” через вкладку “<em>Объекты</em>” в наш проект, появляется возможность использования <strong>JavaScript</strong>.</p>
<figure class=Объект -> JS -> Объект JS» title=»Объект -> JS -> Объект JS» width=»1083″ height=»117″ data-src=»https://habrastorage.org/getpro/habr/upload_files/cd0/8d2/ae1/cd08d2ae114e0910bb672af88e6791fc.jpg» data-blurred=»true»/><figcaption>Объект -> JS -> Объект JS</figcaption></figure>
<p>Чтобы наш “<em>Объект JS</em>” не сливался с фоном — добавим изображение. В дальнейшем нам это пригодится для обработки события, например нажатие по объекту. Изображение добавляется  в настройках “<em>Объекта JS</em>” через “<em>Библиотеку изображений</em>”. Есть возможность выбрать картинку среди стандартных, либо загрузить свою.</p>
<figure class=Фигура -> Исп. изображение -> Библиотека изображений…» title=»Фигура -> Исп. изображение -> Библиотека изображений…» width=»493″ height=»451″ data-src=»https://habrastorage.org/getpro/habr/upload_files/2cd/778/9e5/2cd7789e5308d5af6e14d93c4bf64de5.jpg» data-blurred=»true»/><figcaption>Фигура -> Исп. изображение -> Библиотека изображений…</figcaption></figure>
<p>От производителя оборудования есть прекрасная <a href=документация про «JS Object» . В одном из примеров можно найти библиотеку для отправки POST или GET запросов, она нам понадобится для работы с Telegram Bot API. Скачиваем ее и подключаем через модуль “JS Ресурс”.

Объект -> JS -> JS Ресурс» title=»Объект -> JS -> JS Ресурс» width=»1083″ height=»117″ data-src=»https://habrastorage.org/getpro/habr/upload_files/4fb/e2e/5f2/4fbe2e5f2ccaf21fda939ca8bda51d66.jpg» data-blurred=»true»/><figcaption>Объект -> JS -> JS Ресурс</figcaption></figure>
<figure class=Добавить файл -> OK» title=»Добавить файл -> OK» width=»640″ height=»567″ data-src=»https://habrastorage.org/getpro/habr/upload_files/578/67a/fc7/57867afc76ba8ad7c080f9cbe337fd02.jpg» data-blurred=»true»/><figcaption>Добавить файл -> OK</figcaption></figure>
<p>Давайте создадим класс и опишем методы отправки и приема сообщения, а также добавим функционал для создания кнопок в боте.</p>
<pre><code class=const request = require('./request-0.0.2.js'); export class TelegramBot { constructor(token) { this.token = token; this.url = `https://api.telegram.org/bot${this.token}`; this.keyboard = Array(); this.resultUpdates = {}; }

В request мы предварительно подключаем скачанную ранее из документации библиотеку, а в конструкторе класса TelegramBot присваиваем первоначальные значения свойствам.

●    token — токен, полученный от BotFather, передаваемый при создании экземпляра класса в качестве аргумента

●    url — будет хранить ссылку API Telegram

●    keyboard — массив для функциональных кнопок, которые будут передаваться вместе с сообщением пользователю

●    resultUpdates — ассоциативный массив для хранения последнего сообщения

Получение токена с BotFather я описывать не буду, на Хабре и так полно статей на тему чат-ботов в Telegram (вот к примеру отличная подробная статья).

Далее описываем методы созданного нами класса:

    makeButton(button){         this.keyboard.push(button)     }

makeButton принимает на вход в качестве аргументов массив из названий кнопок и добавляет их в один ряд. Например код:

makeButton(['Температура','Давление']);

При передаче сообщения добавит нам такие кнопочки:

Чтобы добавить кнопки рядом ниже необходимо снова использовать метод makeButton и передать ему названия кнопки.

makeButton(['Скорость']);

Результат будет таким:

Далее опишем метод отправки сообщения:

sendMessage(message, chatid){         var final_url = `${this.url}/sendmessage?`;         var json = {             "chat_id": chatid,             "text": message         };         if (this.keyboard != 0) {             json['reply_markup'] = {                 "resize_keyboard": true,                 "keyboard": this.keyboard             }         };         var jsonData = JSON.stringify(json);         request.post({             url: final_url,             header: {                 "content-type": "application/json; charset=utf-8",             },             data: jsonData             },              (error, response, body) => {                 if (error == "No error") {                     console.log("body:", body);                 }                 else {                     console.log("error:", error);                     console.log("response:", response);                     console.log("body:", body);                 }             }             );     }

sendMessage отправляет сообщение пользователю методом запроса POST, в качестве аргументов принимает message (текст сообщения) и chatid (id пользователя). Свой id можно например узнать через данного бота. Если данные успешно доставлены — выводим в консоль тело ответа от сервера, в случае ошибки совместно с телом в консоль дополнительно производится вывод информация о ошибке.

getUpdates(){         var final_url = `${this.url}/getUpdates?offset=-1`;         request.get({               url: final_url             },              (error, response, body) => {                 if (error == "No error") {                     var body_json = JSON.parse(body);                     this.resultUpdates = body_json.result[0];                 }                 else {                     console.log("error:", error);                     console.log("response:", response);                     console.log("body:", body);                 }             }             );         return this.resultUpdates         }     }

С помощью метода getUpdates получаем все обновления от сервера Telegram и возвращаем последнее сообщение.

Минимальный необходимый функционал реализован, сохраняем данный класс в отдельный файл и подключаем его в EBPro через инструмент “JS ресурс”, как делали это ранее с библиотекой для отправки POST и GET запросов.

Добавить файл -> OK» title=»Добавить файл -> OK» width=»633″ height=»559″ data-src=»https://habrastorage.org/getpro/habr/upload_files/851/37d/2e6/85137d2e6db4ba0a904af49214f8d42b.jpg» data-blurred=»true»/><figcaption>Добавить файл -> OK</figcaption></figure>
<p>Для описания логики работы «<em>Объект JS</em>» в <strong>EBPro</strong> необходимо перейти в его параметры, на вкладку “<em>Исходный код</em>”. </p>
<figure class=

Заполняем содержимое.

const telegramBot = await import('/weintek_telebot.js'); var bot = new telegramBot.TelegramBot('TOKEN') var chats = {} var mouseArea = new MouseArea(); this.widget.add(mouseArea);

В telegramBot импортируем файл с ранее написанным классом.

bot — экземпляр класса telegramBot с переданным в качестве аргумента токеном от BotFather.

chats — именованный массив, понадобиться для хранения ID пользователей написавших нашему боту и ID последнего сообщения

mouseArea  — экземпляр, входящего в стандартную библиотеку класса MouseArea, подробнее о нем можно почитать в документации, с помощью него мы будем обрабатывать событие “нажатия по области” и осуществлять рассылку сообщений.

Добавляем кнопки:

bot.makeButton(['Температура','Давление']); bot.makeButton(['Скорость']);

Теперь, по традиции всех примеров Телеграм ботов, реализуем функцию ECHO бота (при получении сообщения бот будет отправлять его копию в ответ). Для этого будем использовать функцию setInterval, которая вызывает callback функцию с определенным интервалом времени, в нашем случае 500 мс.

setInterval(() => {    var message = bot.getUpdates();    var chatId = message.message.from.id    var messageId = message.message.message_id    var text = message.message.text    if (!(chatId in chats)){        chats[chatId]=[messageId, text];        bot.sendMessage(text, chatId);    }    else {        if (chats[chatId][0] != messageId){            chats[chatId][0] = messageId;            bot.sendMessage(text, chatId);        }    }    } , 500);

В message мы сохраняем объект последнего сообщения, а дальше уже из него вытягиваем необходимые в дальнейшем данные

●        chatId — хранит ID пользователя.

●        messageId — ID сообщения, по которому мы будем определять произошло ли его обновление

●        text — текст сообщения

Далее мы проверяем есть ли в нашем списке такой пользователь, если его нет, то запоминаем его в chats для использования его в будущей рассылке 🙂 также не забываем отправить ему копию его же сообщения.

Ну что? Осталось только написать код для рассылки сообщений?

Для этого  к mouseArea подключаем обработчик события ‘click’ и описываем для него callback функцию, которая перебирает значения с массива chats, но если он еще пустой просто ругаемся в консоль. ¯\_(ツ)_/¯

mouseArea.on('click', (mouseEvent) => {  if (!(Object.keys(chats).length == 0)){      for (var key in chats) {          var mes = bot.sendMessage('Привет! Я Weintek', key);      }  }  else {      console.log('Боту еще никто не отписал!!');  } });

Кстати, для проверки нашего проекта не обязательно иметь панель физически, его можно запустить прямо в среде разработки EBPro с помощью инструмента Оффлайн симуляция.

Проект -> Оффлайн симуляция» title=»Проект -> Оффлайн симуляция» width=»647″ height=»118″ data-src=»https://habrastorage.org/getpro/habr/upload_files/610/dc7/db6/610dc7db60338b53ad1811199ffcd2c4.jpg» data-blurred=»true»/><figcaption>Проект -> Оффлайн симуляция</figcaption></figure>
<p>Запускаем симуляцию:</p>
<figure class=

Все работает! Бот нам отвечает и отправляет сообщение, когда происходит нажатие по объекту JS.

Для просмотра диагностической информации или то что мы отправляем в консоль с помощью функции console.log()  — в режиме оффлайн симуляции запускаем инструмент “Диагностировать”:

Остается только протестировать проект на реальном устройстве. =)

Весь код и пример проекта для EBPro лежит на гитхабе.


ссылка на оригинал статьи https://habr.com/ru/post/709010/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *