MPCMeter — индикация прогресса просмотра видео. Arduino + JavaScript

Вместо введения Спасибо моему анонимному хабрадедуморозу за подарочек (pro mini). Долго колебался, что с ней делать. Махнул рукой и заказал в дополнение китайскую посылочку…Спустя месяцок настало и моё время «помигать светодиодом» ;).Идея Пока ехала посылка, думал что бы такого сделать. В итоге принято решение сделать что-нибудь чуть больше, чем помигать светодиодом.Идея заключается в следующем — отобразить прогресс просмотра видео, используя какой-нибудь индикатор.7e62f52570214eb5b2582ae3d681845f.pngЗадача вытащить статистику по запущенному фильму; обработать и передать в arduino данные; отобразить прогресс на индикаторе. Для нетерпеливых сразу результат [embedded content]Реализация 1. MPC Сколько себя помню, на ПК у меня всегда установлен Media PLayer Classic. Оказывается MPC умеет отдавать статистику по, скажем так, текущей сессии в виде html-странички со следующим содержанием: HTML MPC-HC WebServer — Variables

D:%5cFILMS%5cIts.Always.Sunny.in.Philadelphia.S10E10.720p.WEB.rus.LostFilm.TV.mp4

D:\FILMS\Its.Always.Sunny.in.Philadelphia.S10E10.720p.WEB.rus.LostFilm.TV.mp4

D:%5cFILMS

D:\FILMS

1

Пауза

1069384

00:17:49

1255210

00:20:55

75

0

1

0

Что бы добиться от него такого функционала, нужно проставить галочку «Слушать порт» в настройкахНастройки 2407fccae9134125bb35900dc6689c09.png Всё самое важное содержится в тегах

значение

Остаётся только разобрать их и выбрать нужное.2. NodeJS Разбирать страничку будем при помощи NodeJS. Кстати, страница доступна по адресу localhost:13580/variables.html (порт из настроек).Всю логику можно разделить на 3 блока: модуль работы с MPC web-сервером; модуль обработки данных; модуль работы с arduino. Далее основные моменты. Весь проект вместе с кодом можно глянуть на imagegithubНемного js При помощи родного http.get и обещаний обращаюсь к нашей странице main.prototype.get = function (){ var that = this return new Promise (function (done){ http.get (that.mpc_uri, function (res) { res.on ('data', function (chunk) { that.mpc_obj.parse (chunk) done (that.mpc_obj.get ()); }); }).on ('error', function (e) { done (e.message); }); }) } Методом parse объекта mpc_obj разбираю полученные данные MPC_obj.prototype.parse = function (data){ var obj = {} data.toString ().split ('\n').forEach (function (line){ // отбираем параграфы, так как параметры только в них if (match=/\

')+1, line.lastIndexOf ('<')) } }) this.settings=obj; } На выходе имеем вот такой объект { filepatharg: 'D:%5cmbrr555.avi', filepath: 'D:\\mbrr555.avi', filedirarg: 'D:%5c', filedir: 'D:\\', state: '1', statestring: 'Пауза', position: '1023', positionstring: '00:00:01', duration: '114906', durationstring: '00:01:54', volumelevel: '77', muted: '0', playbackrate: '1', reloadtime: '0' } Подготавливаем данные для arduino // Возвращает прогресс просмотренного MPC_obj.prototype.getProgress = function(){ return (this.settings["position"]/this.settings["duration"]).toFixed(5) } // Возвращает прогресс для ШИМ (PWM) 1,0 -> 255 MPC_obj.prototype.PWM = function (){ return (this.getProgress ()*255).toFixed (0) } Общение с arduino происходит путём обмена данными на com-порту. Для работы с com выбрал библиотеку imagenode-serialportПодключаемся с её помощью к порту com5 и устанавливаем скорость var SerialPort = require ('serialport').SerialPort; var serialPort = new SerialPort («COM5», { baudrate: 57600 }, false); Открываем порт и посылаем в ответ arduino наш прогресс каждый раз, когда она попросит serialPort.open (function (error) { if (error) { console.log ('failed to open: '+error); } else { console.log ('open'); //получил данные от arduino serialPort.on ('data', function (data) { main.init (function (a){ //послал в ответ прогресс фильма serialPort.write (a); }); }); } }); 3. Arduino Теперь железо. Данные для arduino мы подготовили, теперь определимся с той самой индикацией. Для отображения прогресса я выбрал вот такой очень дешёвый модуль вольтметра и немного его «подкрасил»cb2c8717c58341609195f17c40cfcff4.pngЧуть подробней Оказывается, крышка держалась на… липкой ленте и легко снималасьb1b57c836b1f4384b3fdcba585328ede.pngНу, а далее размеры и пара новых панелек7adb29f46d4d477a95f95dff0886a9ac.png В arduino мы посылаем данные о прогрессе фильма и пропорционально изменяем напряжение на одной из ног микроконтроллера. Принципиальная схема (наличие светодиода для того, что бы им помигать в конце сеанса ;))496a1f5e255a4f8abfa0ab81c8099eac.pngТеперь запрограммируем наш микроконтроллер.В переменную inByte будем считывать данные, полученные по com-порту. Вешаем на 3й пин светодиод, а на 9й — вольтметр. Устанавливаем точно такую же скорость как и раньше. loop — наш бесконечный цикл. Каждые 100 мс отправляем в порт абстрактные данные Serial.print ('A'). Ждём наличие ответа Serial.available () > 0. Если на ПК запущен MPC и nodeJS-приложение, которое возвращает прогресс, то чуть подсветим светодиод на 3 м пине analogWrite (3, 5) и передадим на 9й пин вольтметра значение прогресса analogWrite (9, inByte). Функция analogWrite передаёт значения от 0 до 255, что в нашем случае соответствует от 0В до 5В. Тут нужно почитать про ШИМ (PWM) — это всё благодаря ему.Когда мы просмотрели половину фильма, в этот момент на 9й пин будет передано 255/2 = analogWrite (9, 127), что соответствует 2,5В на вольтметре. Как только фильм закончен — бодренько мигаем светодиодом ;) int inByte = 0; void setup () { pinMode (9, OUTPUT); pinMode (3, OUTPUT); analogWrite (3, 0); analogWrite (9, 0); Serial.begin (57600); } void loop () { Serial.print ('A'); delay (100); if (Serial.available () > 0) { analogWrite (3, 5); inByte = Serial.parseInt (); analogWrite (9, inByte); if (inByte==255) analogWrite (3, 255); } } Вот так это всё выглядит в живую на макеткеfa4b778139cf456c8002e68dbb2c8a27.pngда ещё и на видео ;)[embedded content]Кстати в этом проекте использован как раз подарочек от того самого хабрадедамороза.PS.Рядом лежит Attiny13, как время будет — попробую перенести всё на неё.Ссылки: Если где-то написал полную ерунду или ошибся — подсказывайте, подправлю ;). Спасибо за внимание.

© Habrahabr.ru