Удаленное управление ардуинкой (через LAN)
- Войдите на сайт для отправки комментариев
Сейчас занимаюсь тем, чтобы организовать дистанционное управление ардуинкой через LAN. Особенность того, что мне требуется - нужно не просто "дать команду" ардуинке, но и получить от нее ответ.
Архитектура решения следующая: есть веб-сервер с php и mySQL, который крутится в домашней сети, но так же доступен "снаружи". Внутри домашней же сети находится ардуинка с LAN (wiznet).
Сейчас ардуинка спокойно шлет данные веб-серверу (метод POST), т.е. поток данных от ардуинки к веб-серверу уже есть.
А вот как организовать режим "запрос-ответ" (запрос от сервера, ответ - от ардуинки)?
Предлагаю обсудить различные варианты (пока не могу определиться, что же выбрать).
Из того, что уже смотрел - "поднять" на ардуинке веб-сервер и в зависимости от запроса (GET) делать опредленное действие (в GET-запросе кодировать передачу команды - это все просто) и в зависимости от исполненного действия в ответ формировать страницу с данными, которые являются "ответом" на исполненную команду.
Вроде как все просто, но если с ардуинкой в данном случае понятно, то с полноценным веб-сервером - совершенно не понимаю, как к этому подойти (типа, генерация страницы, по клику на кнопку инициировать GET-запрос (кстати, как это сделать?), .. а как дельше сервером получить ответ и какими средствами распарсить ответ?)
Еще можно посмотреть в строну UDP - и "вроде как" тоже все понятно. Есть соответствующий пример с ардуинкой, для php нашел код, как отправить UDP-сообщение. Ардуинка это сообщение принимает (использовал стандартный пример).. но вот как принять ответ ардунки средствами php? Еще, кстати, смущает, что UDP - "ненадежный".
Или я вообще не туда смотрю?
эх.. не хотелось мне ajax учить, но, похоже, придется.
Поправьте, если я неправ.
Сейчас видится следующее решение:
1. Есть страница на веб-сервере, где есть какие-то элементы управления (форма, кнопки и т.п.)
2. на этой странце инициируем какой-либо запрос (скорее всего, это будет GET) к ардуинке
3. ардуинка в ответ выдаст xml (структуру какую-нибудь логичную придумать, чтобы попроще было разбирать)
4. страница на веб-сервере получив конкретный ответ что-то сделает с отображением элементов на странице (кнопку перекрасит, текст какой-нибудь поменяет и т.п.).
Так?
AJAX - тут не причем. Вернее причем, но это "потом". Это обертка над GET/POST поэтому вначали их работы добится нужно.
Весь описанный FLOW не верен (хотя близко). Явно на лицо не четкое понимание как же браузер общается с сервером и как работает Http протокол.
Страницы на сервере - у вас нет. Страница - это в бразуере. А на сервере у вас есть какой-то обработчик запроса от бразера. Общий flow примерно такой:
1. Браузер запрашивает какой-то, обработчкий, скажем handler1.php
2. Тот отдает браузеру HTML страничку (c формочками, кнопками и проч.). Браузер рисует ее.
3. Пользователь на формочке, нажимает нопку Submit, и при этом у кноки Action стоит handler2.php
4. Браузер посылает POST запрос обработчку handler2.php (и ждет от него ответа, в виде новой HTML страницы)
5. Handler2.php начинает обрабатывать запрос
5.1. Читает посланные данный из Request, на основании их
5.2 Строит запрос к ардуине (POST или GET) и делает, уже от своего имени, запрос к ардуине (то есть для ардуины он выступает в роли браузера)
5.2.1. Ардуина получает запрос от Handler2.php, читает посланные данные и формирует какой-то ответ.
5.3. handler2.php получает ответ ардуины, анализирует его и на его основании формирует html ответ браузеру
5.4. Браузер дождался ответа от handler2.php, это какой-то html, его он его показывает как "новую страницу".
Общий поток данных выкглядит так:
Вначале запрос: browser->handler1.php->arduino
А отом эта цепочка "откручивается" назад
Ответы arduino->handler1.php->browser
Это примерно как начальник (браузер) говорит заму (Серверу) "сделай мне отчет по продажам". Зам (сервер/handler2.php)- вызвает Васю-дворника(ардуино) и спрашивает: "Сколько лопат ты сломал в этом году?". Вася отвечает - пять. Зам открывает ворд, красиво оформляет этот ответ в виде трех страниц текста, накладывает резолюцию "вася криворукий дятел" и отсылает этот ответ босу (браузеру).
А Ajax у вас тут выйдет на сцену, когда вы захотите что-бы общение браузера и сервера (.php) происходило без видимой для пользователя перезагрузки страницы.
Тогда, по нажатию какой-то кнопки на странице, у вас будет запускатся javascript (а не отсылатся форма не сервер), который уже сам сделает запрос на сервер, получит от него ответ и исходя из него каким-то образом изменит DOM (HTML) текущей открытой в браузере страницы.
Алексей, спасибо (если честно, то ждал как раз Вашего ответа ;)), очень хорошо расставляете все "по местам".
Мое понимание было именно таким (но не с таким количеством деталей) и описано куда скуднее (и без наглядного примера).
На текущем этапе уже реализовал пункт 5.2.1 - ардуина принимает (и распарсивает) GET-запрос, выполняет требуемое и в ответ формирует XML
Взаимодействие с ардуинкой непосредственно из браузера работает, теперь осталось "Сервер" сделать.
P.S. недюсь, этот топик кому-то еще пригодится.
Ну начали вы с вполне правильного пункта. Я бы тоже именно с него начинал :)
Вот только выбор XML-ля вызвает сомнение. Я понимаю что "модный" (хотя пик моды прошел года три читыре назад, когда пихали его везде, где нужно и не нужно). Стандарты это хорошо. Но если начать XML реализовывать в полной мере, с namespace, CDATA, квотингом значений, энтитями, проверкой схем и т.п..... даже на компе полностью "по стандартам" мало у кого хватает сил, ограничиваются XML-Ля подобным :)
Да IMHO XML тяжеловат он для ардуины. Это строки. А памяти мало. Для веб решения - было-бы более естественным выбрать JSON (а для ajax решений - это вообще "родное") или даже какой-то собственный формат, максимально упрощенный (что-бы проще парсить было).
Я, в аналогичном своем решеине так и делаю, просто данные через запятую одной строкой гоняю :) Так как у меня "клиентом" ардуины может выступать не только сервер, но и другая ардуина. Поэтому важно что-бы и сама арудуина могла распарсить ответы максимально просто. А писать на ардуине XML или JSON парсер - не хотелось почемуто ;)
Кроме того, на будущие, это позволит более "нативно легко", при необходимости, если скорости станут важны - перейти на бинарный формат, а не текстовый. С JSON это будет проблематично, с XML - вообще не представляю.
Сейчас подумываю перейти на формат команд в виде S-expressions. Но пока в раздумьях, оправдают ли выгоды усилия на переход.
P.S. И тут я зовусь leshak ;) Не нужно нарушать косплей ;)
leshak, исправляюсь :)
Переход на JSON прошел максимально гладко. Достаточно было шаблон для ответа поправить и изменить Content-Type - теперь на выходе вместо XML получился JSON.
Если не сложно, можете "ткнуть" носом, где можно глянуть примерчик, где релизовано:
Тогда, по нажатию какой-то кнопки на странице, у вас будет запускатся javascript (а не отсылатся форма не сервер), который уже сам сделает запрос на сервер, получит от него ответ и исходя из него каким-то образом изменит DOM (HTML) текущей открытой в браузере страницы.
Можно в каком-нибудь сильно усеченном виде: кнопка и одно значение на странице, по клику на кнопке -> запрос к ардуинке -> ответное значение -> обновить на исходной странице?
вопрос снимается - сам все нашел.
Не знаю что вы нашли, но на всяк случай: для манипуляции DOM и ajax запросами на данный момент библиотека jQuery де факто является стандартом (не буду расписывать, документации и примеров - валом. в том числе и на русском). Так же желательно знать, хотя-бы основы CSS (ну хотя-бы селектор по id уметь написать).
Вообщем-то ее вполне хватит, но если собираетесь делать суръезное UI на клиенте то можно посмотреть еще (дополнительно к jQuery) на вещи типа KnockoutJS (мое вкусовое предпочтение) или его конкуретны типа BackboneJS и AngularJS. Это не обязательно, но на сложных UI сильно облегчает жизнь благодаря использованию паттерна MVC (а когда освоишься с библиотекой, то и простые UI из одной кнопки уже проще через них делать :)
И еще, возможная грабля на пути AJAX. Секьюреные ограничения браузеров. Если вы html/js загрузили с одного домена (сервер), а запрос делаете на другой домен (ардуина) - браузер может и не пустить. Есть конечно способы обхода (crossdomain.xml, origin-заголовки, jsonp и т.п.) - но... лучше не лезть в это болото. Там могут начать выплывать всякие "разные браузера по разному" (особенно IE) наиболее простым и 100% надежным решением будет именно server-proxy. То есть ajax запрос идет к серверу (с которого и грузился js), а уж он спрашивает ардуину. Тем более что именно такая схема предполагается в конечном решении, когда ардуина будет спрятана за firewall-лом и не видна из мира.
Для "потестить" же можно, например в хроме заткнуть проверку секьюрности запустив его с флагом --disable-web-security (но, честно говоря сам не проверял). А если с флагом --allow-file-access-from-files (это проверял) то html файлики можно будет запускать прямо с локальной файловой системы, даже без сервера. Вообщем-то со вторым флагом я тестил свою ардуинку ajax запросами, просто запуская html файлик с пути вида C:\MyFolder\MyFile.html
Ну да, туда и "копаю".
Сейчас у меня веб-сервер расположен в домашней сети, но доступен извне по известному (мне) доменному имени.
Ардуинка - в домашней сети, но по конкретному IP. На сервере сделал примитивный "проксик":
Собственно, через него уже работает потихоньку.
Все примерно так, но... желательно завести себе за правило - любой контент получаемый от пользователя (от бразузера) должен проходить на серверной стороне, перед тем как передаватся в какие-то функции через экранирование и/или проверки на его корректность.
В своем коде, вы фактически даете возможность любому, на вашем сервере выполнить функцию file_get_contents и увидеть ее ответ. Хотя и с вашей собственной обязательной добавкой "http://192.168.1.237" - но дальше можно пихануть что угодно (спец-символы, имена локальных файлов, что-то очень длинное для переполнения и т.п.). Возможно, в данном случае ваша "добавка" и спасет вас (просто не помню, давно с Php не работал), но сильно подозреваю что если задатся целью, то через такую кострукцию можно и файлы у вас на сервере смотреть, а если повезет, то даже свой код выполнить.
Вообщем лучше просто "придерживатся стиля" (чем разбиратся с потенциальными уязвимостями конкретных php функций). Проверять входные параметры каким-нибудь regex-сом. Если параметры строковые - экранировать, если цифровые - далать что-то типа int.Parse и т.п.
А если будете в будущем еще базу данных какую-то испльзоватся - так это вообще первое чему учат новичков :)
Вот, к примеру статейка на хабре по этому поводу http://habrahabr.ru/company/xakep/blog/112691/ по file_get_content
или Основы безопасного веб-программирования на PHP
А вообще это целый класс атак по схожему принципу.
А есть еще Межсайтовый скриптинг — Википедия (и тут это тоже проглядывается, мы имеем возможность заставить сервер ответить нужным нам контентом).
Конечно вы строите не банковскую систему и на многие вещи можно плюнуть. Безопастность - тоже стоит усилий/денег. И не всегда возможные ущерб*вероятность выше чем обеспечение безопастности. Но в любом случае лучше плевать осознанно, чем по не знанию.
P.S. Как минимум - можно примернить какой-нибудь url_encode для этого получаемого QueryString перед тем как использовать его для формирования Url.
я это решил ТАКИМ способом, удобно и надежно :)
http://inspiritus.ksduino.info/#device_3314
кстати кнопки можете подергать, на моей стороне мат модель устройства, ничего не взорвется :)