MPCMeter — индикация прогресса просмотра видео. Arduino + JavaScript
Вместо введения
Спасибо моему анонимному хабрадедуморозу за подарочек (pro mini). Долго колебался, что с ней делать. Махнул рукой и заказал в дополнение китайскую посылочку…Спустя месяцок настало и моё время «помигать светодиодом» ;).Идея
Пока ехала посылка, думал что бы такого сделать. В итоге принято решение сделать что-нибудь чуть больше, чем помигать светодиодом.Идея заключается в следующем — отобразить прогресс просмотра видео, используя какой-нибудь индикатор.
Задача
вытащить статистику по запущенному фильму;
обработать и передать в arduino данные;
отобразить прогресс на индикаторе.
Для нетерпеливых сразу результат
[embedded content]Реализация
1. MPC
Сколько себя помню, на ПК у меня всегда установлен Media PLayer Classic. Оказывается MPC умеет отдавать статистику по, скажем так, текущей сессии в виде html-странички со следующим содержанием: HTML
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
Что бы добиться от него такого функционала, нужно проставить галочку «Слушать порт» в настройкахНастройки
Всё самое важное содержится в тегах
значение
Остаётся только разобрать их и выбрать нужное.2. NodeJS Разбирать страничку будем при помощи NodeJS. Кстати, страница доступна по адресу localhost:13580/variables.html (порт из настроек).Всю логику можно разделить на 3 блока: модуль работы с MPC web-сервером; модуль обработки данных; модуль работы с arduino. Далее основные моменты. Весь проект вместе с кодом можно глянуть на')+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 выбрал библиотеку node-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 мы подготовили, теперь определимся с той самой индикацией. Для отображения прогресса я выбрал вот такой очень дешёвый модуль вольтметра и немного его «подкрасил»
Чуть подробней
Оказывается, крышка держалась на… липкой ленте и легко снималась
Ну, а далее размеры и пара новых панелек
В arduino мы посылаем данные о прогрессе фильма и пропорционально изменяем напряжение на одной из ног микроконтроллера. Принципиальная схема (наличие светодиода для того, что бы им помигать в конце сеанса ;))
Теперь запрограммируем наш микроконтроллер.В переменную 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);
}
}
Вот так это всё выглядит в живую на макетке
да ещё и на видео ;)[embedded content]Кстати в этом проекте использован как раз подарочек от того самого хабрадедамороза.PS.Рядом лежит Attiny13, как время будет — попробую перенести всё на неё.Ссылки: Если где-то написал полную ерунду или ошибся — подсказывайте, подправлю ;). Спасибо за внимание.
