...

понедельник, 8 августа 2016 г.

[Из песочницы] Управляем компьютером через браузер

Компьютер давно многим заменил телевизор, а что не хватает компьютеру для комфортного просмотра кино, сериалов и прочего? Мне лично не хватало пульта дистанционного управления.

image

Я не много увлекаюсь веб-программированием в свободное время. Было решено написать свой велосипед и заодно совместить приятное с полезным. Была изучена возможность с помощью консоли управлять компьютером, в первую очередь меня интересовал следующий минимальный объем задач (который немного увеличился в последствии):
  • Возможность отправить ПК в режим сна
  • Возможность выключить громкость

С помощью известного поисковика нашел консольную программу, NirCmd, программа позволяет осуществлять достаточно много действий кроме указанных выше. С основной частью мы определились. Как я говорил, не много изучаю php, веб-сервер у меня как правило запущен постоянно, поэтому ничего специфичного в плане сервера я придумывать не стал. Сервер написан на php и состоит из двух классов: Control, который представляет собой методы которые исполняют консольные команды и Route, который делает валидацию приходящих запросов и исполняет методы класса Control.

Control выгладит вот так (код однотипный, поэтому я сократил):

class Control implements ActionControl {
                protected $Path; //путь до программы nirCmd;
                
                function __construct($p = 'C:/nircmd/nircmd.exe') {
                        $this->Path = $p;
                }
                function standby() {
                        `{$this->Path} standby`;
                }
                function hibernate() {
                        `rundll32 powrprof.dll,SetSuspendState 0,1,0`;
                }
                function reboot() {
                        `{$this->Path} exitwin reboot`;
                }
                function turnOff() {
                        `{$this->Path} exitwin poweroff`;
                }
                function logout() {
                        `{$this->Path} exitwin logoff`;
                }
}

Второй класс, — Route. Собственно к нему обращается клиент. Класс, в первую очередь осуществляет валидацию запроса, и если запрос правильный вызывает методы класса Control.
Выглядит это так:
class Route implements ActionRoute {
                protected $possible = [];               
                protected $ControlObj;
        
                function __construct($obj) {
                        $this->possible = get_class_methods($obj); 
                        $this->ControlObj = $obj;
                }
                function route($arr) { 
                        forEach($arr as $key => $value) {    
                   if (in_array($key, $this->possible) && $value == 'true') {
                        $this->execute($key);
                   } else 
                        {
                                Message::sent('wrong method');
                        }       
                        }
                }
                function execute($c) {
                        $this->ControlObj->$c();
                        Message::sent('executed');
                }
        }

Чтобы получилось в случае чего легко расширить количество методов в классе Control, валидация в классе Route жестко не привязана к определенному списку методов класса Control, точнее привязана, но все возможные методы извлекаются из самого объекта, с ними и идет сравнение пришедших данных.

Сам файл к которому обращается клиент выглядит вот так:

<?
        define("PATH", "C:/nircmd/nircmd.exe"); 
        function __autoload($name) {
                require "class/$name.class.php";
        }
        
        $obj = new Control(PATH);
        $route = new Route($obj);

        if ($_GET) {
                $route->route($_GET);
        }
?>


Если приходит GET запрос, то весь массив отдаем методу route.

Клиентская часть представляет собой кнопки управления и один обработчик, по которому мы шлем данные при помощи ajax на сервер.

var wrapper = document.querySelector(".wrapper");

function getXmlHttpRequest(){
        if (window.XMLHttpRequest) {
                try {
                        return new XMLHttpRequest();
                } catch (e){ }
        } else if (window.ActiveXObject) {
                try {
                        return new ActiveXObject('Msxml2.XMLHTTP');
                } catch (e){}
                try {
                        return new ActiveXObject('Microsoft.XMLHTTP');
                } catch (e){}
                }
        return null;
}

wrapper.addEventListener('click', function(e){
        var target = e.target;

        if(target.tagName!= 'BUTTON') return;
        if (target.getAttribute('data')=='qestion') {
                var yn = confirm("Уверен?");
                if (!yn) return
                        ajaxf(target.id);
        }
        ajaxf(target.id);
})

        function ajaxf($com) {
                var command = $com+'=true';
                var xhr = new getXmlHttpRequest();
                xhr.open('GET', 'remote.php?'+command, true);
                xhr.send();
                xhr.onreadystatechange = function() { 
                        if (xhr.readyState != 4) return;
                        if (xhr.status != 200) {
                        console.log(xhr.status + ': ' + xhr.statusText);
                        } else {
                        console.log(xhr.responseText);
                        }
                }
        }

На сегодня реализован следующий функционал управления:
  • спящий режим
  • гибернация
  • перезагрузится
  • выключить
  • выйти
  • выключить монитор
  • включить/отключить звук по триггеру
  • громкость больше
  • громкость меньше
  • Медиа кнопки, stop/play next/prev

Все, что я хотел получить, получил, но, как говорится, аппетит приходит во время еды. Хотелось бы иметь обратную связь от сервера, т.е. при первом заходе на страницу делать запрос текущего уровня громкости например. К сожалению, nirCmd не возвращает значения при выполнении, поэтому с тем, что имеем сейчас, я не знаю, как это осуществить.

Вопрос безопасности. Хотя это все и крутится на локальной машине, будет очень печально, если доступ к исполнению команд nirCmd будет у злоумышленника, т.к. можно сотворить много деструктивных действий.

Готовый проект на GIthab.

Комментарии (0)

    Let's block ads! (Why?)

    Комментариев нет:

    Отправить комментарий