Я давно интересовался Arduino, и вот однажды решился на покупку этой замечательной платформы. После недолгих поисков приобрел небольшой Arduino kit, в котором, помимо прочего, был ИК-датчик и пульт к нему. Изучив примеры из мануала, понял, что настало время придумать что-то свое. В итоге я решил сделать удаленное управление VLC player’ом, используя магию Arduino и Python3.
Аrduino магия
Схема подключения и скетч честно взяты без изменений из мануала Arduino kit, скачанного с сайта производителя.
/* 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.
ссылка на оригинал статьи http://habrahabr.ru/post/232401/
Добавить комментарий