http://habrahabr.ru/post/232401/
Добрый день, уважаемые читатели.
Я давно интересовался Arduino, и вот однажды решился на покупку этой замечательной платформы. После недолгих поисков приобрел небольшой Arduino kit, в котором, помимо прочего, был ИК-датчик и пульт к нему. Изучив примеры из мануала, понял, что настало время придумать что-то свое. В итоге я решил сделать удаленное управление VLC player’ом, используя магию Arduino и Python3.
Аrduino магия
Схема подключения и скетч честно взяты без изменений из мануала Arduino kit, скачанного с сайта производителя.
Cкетч/*
Arduino Advanced Kit example
Project 11 - IRRemote
* IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
*/
#include <IRremote.h>
int RECV_PIN = 7;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup() {
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value,HEX); // print received values
irrecv.resume(); // Receive the next value
}
}
В итоге, на монитор порта нам приходят коды нажатых клавиш. Опытным путем было выяснено, что подходят разные ИК-пульты. Хотя это известный факт, но для меня это было в новинку. А вот дальше интереснее. VLC media player имеет удобный web-интерфейс. И управлять им можно посредством обычных http-get запросов вида:
«host:port/page.html?var=value&var2=value2&...»
Более подробную информацию можно найти на
videolan.org.
Python3 магия
Используя Python3 и его богатые библиотеки, возможно как посылать http-requests, так и считывать данные с serial port. Этого оказалось достаточно для исполнения моей задумки. Скрипт на Python3 написан с использованием ООП подхода.
Вкратце работа скрипта состоит в следующем:
1. Создаем экземпляр класса vlc_remote_contol, в конструктор передаем адрес нашего Vlc player, список с кодами клавиш, и имя виртуального сom порта.
2. Вызываем метод control в котором происходит считывание с порта кода клавиши.
3. Код клавиши передается в метод __switch_button. где вызывается метод __command с определенными параметрами
4. __command непосредственно осуществляет get запрос к VLC player.
Скриптimport getpass
import time
import subprocess
import requests
import serial
import sys
import lxml.etree as etree
class vlc_remote_contol:
def __init__(self,hst,blist,pname):
self.host = hst
self.btn_list = blist
self.port = serial.Serial(pname, 9600, timeout = 0)
self.__sess = requests.Session()
self.__sess.auth = ('',getpass.getpass())
self.old_vol = self.__get_param(self.__sess.get(self.host+'/requests/status.xml').text, 'volume')
self.curr_vol = 0
def __get_param(self,info,param):
beg = info.find('<'+param+'>')+len('<'+param+'>')
end = info.find('</'+param+'>')
return int(info[beg:end])
def __command (self,host,comm,val):
if (val == ''):
req = self.__sess.get(host+'/requests/status.xml'+'?'+'command='+comm)
else:
req = self.__sess.get(host+'/requests/status.xml'+'?'+'command='+comm+'&val='+val)
req.close()
def __switch_button(self,btn_code):
if (btn_code == 'FFC23D'): ## play/pause
self.__command(self.host,'pl_pause','')
elif (btn_code == 'FF906F'): ## fullscreen
self.__command(self.host,'fullscreen','')
elif (btn_code == 'FFE01F'): ## volume down
self.__command(self.host,'volume','-10')
elif (btn_code == 'FFA857'): ## volume up
self.__command(self.host,'volume','+10')
elif (btn_code == 'FF22DD'): ## rewind back
self.__command(self.host,'seek','-0.5%')
elif (btn_code == 'FF02FD'): ## rewind forward
self.__command(self.host,'seek','+0.5%')
elif (btn_code == 'FFA25D'): ## previous track
self.__command(self.host,'pl_previous','')
elif (btn_code == 'FFE21D'): ## previous next
self.__command(self.host,'pl_next','')
elif (btn_code == 'FF6897'): ## mute
self.cur_vol = self.__get_param(self.__sess.get(self.host+'/requests/status.xml').text, 'volume')
if (self.cur_vol == 0):
self.__command(self.host,'volume',str(self.old_vol))
else:
self.old_vol = self.cur_vol
self.__command(self.host,'volume','0')
else:
pass
def control(self):
print('Success')
while True:
res = self.port.readline().strip().decode("UTF-8")
if (res in self.btn_list):
self.__switch_button(res)
def main():
conf = etree.parse('conf.xml')
vpath = conf.xpath('/document/vpath/text()')[0]
vhost = conf.xpath('/document/vhost/text()')[0]
try:
subprocess.Popen([vpath])
except:
input('VLC player not found')
return
try:
buttons0 = ['FFA25D','FF629D','FFE21D','FF22DD','FF02FD','FFC23D','FFE01F','FFA857','FF906F','FF6897',
'FF9867','FFB04F','FF30CF', 'FF18E7','FF7A85','FF10EF','FF38C7','FF5AA5','FF42BD','FF4AB5', 'FF52AD']
vrc = vlc_remote_contol(vhost,buttons0,"COM3")
vrc.control()
except:
input("Connection or authorization error.")
return
if __name__ == "__main__" :
main()
Заключение
Я понимаю, что не придумал ничего оригинального и нового. Это мой первый опыт в промышленном программировании, до этого были только лабораторные работы в Университете и решение олимпиадных задач. Жду от сообщества конструктивной критики и советов по улучшению скрипта. Пока в планах добавить коды клавиш в сonf.xml файл, что было использовать другие пульты, и возможно простой графический интерфейс.
Все исходники опубликованы на
GitHub.