Ребятушки всем Привет. За последнюю неделю я порядком поднадоел своим активным подписчикам Instagram с темой онлайн термопринтера. Возникало много вопросов, поэтому решил все таки написать статью на эту тему и закрыть вопрос раз и навсегда. вмв
Для тех кто не вкурсе происходящего. Относительно недавно я увлекся темой вендинговых автоматов и волей судьбы у меня появились один за одним, два термопринтера. Первый я благополучно спалил, ну а второй стал отправной точкой для реализации «безумных» идей.
Пролог
Вдоволь наигравшись с распечаткой стандартных примеров из библиотеки Adafruit на Python. Я решил запилить онлайн сервис, для взаимодействия с моими подписчиками. Если брать тех. задание, то все представлялось следующим образом. Подписчик пишет сообщение и оно отправляется на сервер, выводиться на печать, а соответственно подписчик, видит его на экране. Проект как говориться чисто «фо фан».
Сначала подумал про Telegram Bot и Youtube, видел такую реализацию у ребят из Германии. Но когда попробовал, понял, что не удобно. Нужно иметь под рукой или компьютер с телефоном, или быстро переключаться между приложениями на смартфоне. Плюс я хотел все вставить на сайт, а это уже ставило под сомнение мой выбор.
Причем тут Youtube и как он помог
С Youtube тоже немного не задалось. Мне необходимо было реализовать весь сервис на Python, потому что на тот момент я умел работать с термопринтером только на Python. У Youtube довольно странный по моему мнению API для стриминга и отлова сообщений в чате, и совсем нет ботов для моих целей. Сейчас заядлые стримеры должны меня закидать тухлыми помидорами. Но нет. Мне нужен был бот для развертывания на локальном сервере, а не всякие там NightBot и др., фиг знает где, без возможности управления и взаимодействия с термопринтером.
Почему я отказался от банальной формы на сайте и стриминга видеопотока на Youtube с обычной вебки? Все очень просто. У Youtube уже все отработано. Антимат, спам-фильтр, удобный интерфейс, возможность получить имя пользователя. И все бы хорошо, но не дружу я с его API. Написал товарищу, который пару лет назад запустил сервис по онлайн кормежке своего кота на Youtube. Попросил код. Он оказался на Node JS. Пришлось начать изучать JavaScript, но у меня не получилось забрать данные о потоке и стриме по причине разницы версий API. Автор не смог дать детальных объяснений по поводу своего кода и мне пришлось отказаться от затеи с Youtube. Однако в это же самое время я стал параллельно разбираться как мне выводить печать на термопринтер в Node JS. И решение нашлось.
Raspberry Pi. Node JS и Термопринтер.
Не люблю я городить огороды, поэтому решил собрать все на одной платформе. Выбор пал на Raspberry Pi. В первую очередь потому что я работал с термопринтером именно на ней.
И так. Платформа выбрана. Как накатить Node JS и NPM рассказывать в этой статье не буду. Как говорит старый баян — «Google в помощь.» Перейдем сразу к вопросу как заставить печатать термопринтер из JavaScript. Первым делом устанавливаем библиотеку ESCPOS. Советую изучить ее детально, т.к. от типа подключения термопринтера зависит выбор адаптера. Библиотека поддерживает Serial, USB, Ethernet принтеры.
$ npm i escpos --save
Далее создаем файл helloworld.js и пишем следующий код.
const escpos = require('escpos');
// Выбираем тот тип адаптера который подходит для принтера. Для меня это Serial адаптер //
const serialDevice = new escpos.Serial('/dev/serial0', {
baudRate: 19200,
stopBit: 2
});
const options = { encoding: "win1251" /* default */ } // Кодировку можно менять
const printer = new escpos.Printer(serialDevice, options);
serialDevice.open(function(err){
printer
.font('a')
.align('ct')
.style('bu')
.size(1, 1)
.text('Hello World')
.text('Привет Мир')
.cut()
.close();
});
В результате получаем распечатанный текст на английском и русском языке. Друзья. Библиотека поддерживает достаточное количество настроек для вывода и форматирования текста, Bar-коды, печать изображений. Но это выходит за рамки данной статьи. Да и мне по сути нужен только текст.
Twitch Bot. TMI.JS
В результате моих злоключений. Было принято решение искать подходящую платформу с возможностью стриминга, чатом, анимат фильтром, возможностью таймаута для сообщений и др. плюшками свойственными такому сервису. Но самое главное. Это нормальное человеческое API или уже реализованный бот. И как часто у меня бывает, независимо от моего желания, на глаза мне попалась статья о управлении светодиодами с помощью команд в чате сервиса Twitch. И каково было мое удивление, когда я узнал, что бот можно написать на JavaScript.
Tmi.js модуль позволяющий в пару строк написать минимально необходимого мне бота. Для начала устанавливаем и подключаем модуль tmi.js в созданном файле print.js
1 |
npm i tmi.js --save |
1 |
var tmi = require ('tmi.js'); |
Теперь пишем настройки подключения к серверу для tmi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var options = { options: { debug: true }, connection: { cluster: "aws", reconnect: true }, identity: { username: "your-bots-username-here", password: "oauthtokenhere" }, channels: ["your-channel-here"] }; |
options и connections содержат базовые настройки подключения, давайте подробней разберем остальное.
- username — здесь мы указываем никнейм нашего бота
- password — сюда вставляем OAuth token который можно получить на сайте twitchapp
- channels — указываем название канала к которому наш бот должен подключится
Подключаем нашего бота
1 2 |
var client = new tmi.client(options); client.connect(); |
Культура бота
Для начала давайте сделаем что-бы наш бот приветствовал каждого кто заходит к нам на канал
1 2 3 |
client.on("join", function (channel, username, self) { client.action("your-channel-here", username + " , glad to see you!"); }); |
Теперь наш бот культурный — будь как наш бот.
Кто здесь?
Давайте теперь научим нашего бота различать кто написал сообщение — пользователь или админ
1 2 3 4 5 6 7 8 |
client.on('chat', function (channel, username, message, self) { if(username.username === "your-channel-here"){ // Admin commands } else { // Users commands } }); |
Здесь мы указываем что если никнейм пользователя который написал сообщение равен названию нашего канала — значит это вы (админ). Если нет, тогда обычный пользователь.
Команды пользователя
У пользователь будут команды которые возвращают ссылки на соц.сети. Потому, много кода не нужно, так как ответы статичны.
1 2 3 4 5 6 7 8 9 |
switch (message) { case "!fb": client.action('your-channel-here', 'your-fb-link-here'); break; case "!twt": client.action('your-channel-here', 'your-twitter-link-here'); break; default: } |
Команды админа
А для админа мы дадим возможность задавать timeout сообщений для пользователь и чистить чат. Для начала давайте узнаем есть ли команда в сообщение админа.
1 2 3 4 5 6 7 |
function splitMessage(message) { if ((message.indexOf('!to')) !== -1){ timeOut(message); } else if ((message.indexOf('!clear')) !== -1){ client.clear("your-channel-here"); } } |
Тут мы написали функцию которая получает сообщение пользователя, проверяет есть ли в нем !to или !clear. Если находим !to тогда будем вызывать функцию timeout-a которую сейчас напишем. А если нашли !clear — вызываем функцию модуля tmi clear
1 2 3 4 5 6 7 |
function timeOut(message) { splitMSG = message.split(" "); timeoutUserName = splitMSG[1]; timeoutDuration = splitMSG[2]; client.timeout("your-channel-here", timeoutUserName, timeoutDuration); client.action('your-channel-here', timeoutUserName + ' now u have timeout mode! Duration: ' + timeoutDuration); } |
Здесь мы разбираем сообщение используя метод split. И разбиваем нашу строку на отдельный строки. Так как команда должна получаться 2 переменные — username (никнейм жертвы) и время в секундах на сколько мы будем ставить ей таймер. Дальше мы вызываем функцию timeout с модуля tmi передавая ему названия канала, никнейм жертвы и время. И выводим сообщение для нашей жертвы, что она получила таймер.
Теперь отрываем консоль и запускаем нашего бота.
1 |
node print.js |
Запуститься бот и можно проверить как он взаимодействует с чатом. Костяк бота готов. Теперь добавим в код функцию которая будет получать сообщение от пользователя. И если в ней есть !print вызывать функцию printOut
1 2 3 4 5 6 7 8 9 |
// Print command function printMessage(message) { if ((message.indexOf('!print')) !== -1){ printOut(message); } else if ((message.indexOf('!clear')) !== -1){ client.clear("your-channel-here"); } } |
Напишем функцию printOut. В ней сразу уберем команду !print из текста сообщения и передадим его в переменную.
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 38 |
function printOut(message) { textMSG = message.split(" "); printMSG = textMSG[1]; console.log(printMSG) textMSG.splice(0,1); finMSG = textMSG.join(' '); console.log(user); console.log(finMSG) // Select the adapter based on your printer type // const serialDevice = new escpos.Serial('/dev/serial0', { baudRate: 19200, stopBit: 2 }); const optionss = { encoding: "win1251" /* default */ } // encoding is optional const printer = new escpos.Printer(serialDevice, optionss); serialDevice.open(function(err){ printer .font('a') .align('ct') .style('bu') .size(1, 1) .text('________________________________') .align('lt') .text('Message from: ' + user) .text('" ' + finMSG + ' "') .align('ct') .text('________________________________') .feed(3) .cut() .close(); }); } |
Используя уже знакомую переменную split, разбераем сообщение. Преобразовываем его в массив, удаляем команду !print при помощи метода splice и объединяем все элементы массива в строку при помощи метода join. В результате в переменной finMSG получаем текст отправленного сообщения в чате.
В этой же функции добавляем код из примера helloworld.js немного видоизменив его, для работы с принтером и выводим на печать наше сообщение из чата. Для этого используем команду .text(‘» ‘ + finMSG + ‘ «‘) Уверен, если вы перед тем как начать писать бота для Twitch, хорошо отработали все с модулем ESCPOS у вас не должно возникнуть никаких вопросов. Это самый простой пример вывода сообщения. Естественно можно навести рюшечки и все облагородить, но не в этом состоит наша основная задача. Главное разобраться как это работает и ну а дальше… Дальше только полет вашей фантазии.
Ах да еще один важный момент. Сриминг на Twitch при помощи Raspberry Pi. К сожалению всем известная OBS Studio не работает на Raspberry. Почти единственным рабочим вариантом для стриминга при помощи веб-камеры является утилита ffmpeg. Друзья дорожка на которую становиться geek задумывая стримить с Raspberry очень длинная и тернистая, порой даже приходиться переходить на темную сторону силы. Поэтому я приведу только работоспособную команду для запуска стрима, а вот установку и сборку ffmpeg и дальней злоключения оставлю на откуп вам.
sudo ffmpeg -v error -f v4l2 -i /dev/video0 -s 1280x720 -f default -c:v libx264 -pix_fmt yuv420p -preset veryfast -b:v 2000k -g 60 -c:a aac -b:a 128k -ar 44100 -maxrate 500k -bufsize 250k -strict experimental -f flv rtmp://livewaw.twitch.tv/app/live_278195168_вашкодтрансляциинаTwitch
Кстати вот сколько вы уже напечатали за два дня теста.
Друзья. Проект завершился. Но посмотреть как это было можно на видео ниже.
Друзья. Если вам понравилась эта статья, поделитесь ей в социальных сетях. Обязательно напишите комментарий если у вас возникли вопросы. Мне важно ваше мнение. И поддержите проект монеткой на страничке Donate.