Raspberry pi для программирования программирование на python

5 способов сделать Python-сервер на Raspberry Pi. Часть 1

Сегодня в большом числе проектов домашней (и не только) автоматизации используется Raspberry Pi. При этом достаточно удобно иметь не только прямой доступ к устройству, но и использовать браузер — это позволяет выполнять необходимые действия и с компьютера, и с мобильного телефона, и даже удаленно из любой точки мира.

Допустим, у нас уже есть супер Python-программа, делающая что-то очень важное, от мигания светодиодом до управления «умным домом» или хотя бы кормушкой для кота. Я покажу разные способы, от простого к сложному, как сделать web-доступ к такому приложению, добавив немного кода.

Статья расчитана для начинающих, профи вряд ли найдут здесь что-то кардинально новое, ну а новичкам в Linux надеюсь, будет полезно. Для тех кому интересно, продолжение под катом.

Примечание: эта статья является своего рода «экспериментом», как-то в комментариях жаловались что на Хабре недостаточно статей для начинающих. Я попытался восполнить пробел, ну а по оценкам будет видно, имеет смысл продолжать в таком формате или нет.

Настройка Raspberry Pi

Будем надеятся, что у читателя есть Raspberry Pi, которая подключена к домашней сети через WiFi или Ethernet, и читатель знает что такое IP адрес и как зайти удаленно на Raspberry Pi через SSH при помощи putty. Мы будем рассматривать так называемую headless-конфигурацию — без клавиатуры и монитора. Но перед тем, как делать что-то с Raspberry Pi, пара небольших лайфхаков.

Совет N1. Чтобы что-то удаленно делать с Raspberry Pi, на нем нужно настроить SSH, а по умолчанию он выключен. Можно пойти традиционным способом, и запустить стандартный конфигуратор, но можно сделать проще — после записи образа диска достаточно создать пустой файл ssh (без расширения) в корне SD-карты. Дальше, после загрузки Raspberry Pi, SSH будет сразу активен.

Чтобы зайти удаленно на устройство, нужно узнать IP-адрес Raspberry Pi. Для этого достаточно открыть контрольную панель своего маршрутизатора, найти там список DHCP-клиентов, скопировать оттуда нужный IP-адрес (например, это будет 192.168.1.102), и ввести команду putty.exe pi@192.168.1.102 (для Windows) или ssh pi@192.168.1.102 для Linux или OSX.

Однако, IP-адреса могут меняться, например после перезагрузки маршрутизатора, это не всегда удобно. Из этого следует Совет N2 — настроить статический IP-адрес. Для этого на Raspberry Pi выполняем команду sudo nano /etc/dhcpcd.conf, и вводим следующие настройки:

Если нужен адрес WiFi, то интерфейс будет wlan0, если Ethernet то eth0. IP-адреса разумеется, нужно тоже подставить свои. После перезагрузки убеждаемся что IP-адрес правильный, введя команду ifconfig.

Теперь все готово, можем приступать к Python. Все примеры даны для Python 3.7, т.к 2.7 уже давно устарел, и поддерживать его бесмысленно. Но при небольших изменениях кода все заработает и там, если нужно. Кстати, язык Python является кроссплатформенным — это значит что весь приведенный ниже код можно запустить и на Windows и на OSX, ну и разумеется, на Raspberry Pi. Из этого следует Совет N3 — отлаживать программу можно и на обычном ПК, а уже готовую версию заливать на Raspberry Pi. Возможно, придется лишь сделать функции-обертки для методов GPIO, все остальное будет работать.

Итак, наша задача — обеспечить доступ к приложению через обычный браузер. Ибо это стильно-модно-молодежно, ну и «интернет вещей» это наше все.

Способ 1: командная строка

Самый простой способ, не требующий вообще никакого программирования.

Выбираем нужную папку на Raspberry Pi, и вводим команду:

Все, на Raspberry Pi работает файловый сервер! Достаточно зайти на страницу http://192.168.1.102:5000 и мы увидим наши файлы в браузере:

Это достаточно удобно, если нужно открыть удаленный доступ к каким-либо файлам с минимумом затраченных сил. Можно также ввести команду sudo python3 -m http.server 80 и запустить сервер со стандартным 80-м портом, это позволит не указывать порт в адресной строке браузера.

Кстати, если мы хотим, чтобы сервер работал и после закрытия терминала, можно использовать команду sudo nohup python3 -m http.server 80 & — это запустит процесс в фоне. Убить такую программу можно перезагрузкой, или вводом в командной строке команды sudo killall python3.

Способ 2: SimpleHTTPServer

Мы можем довольно просто интегрировать такой же сервер в нашу программу на Python, для этого достаточно запустить его отдельным потоком при старте программы. Теперь, нам не надо возиться с командной строкой, пока программа запущена, сервер будет работать.

Команда os.chdir является опциональной, если мы хотим предоставить доступ из сервера к какой-то другой папке, кроме текущей.

Способ 3: HTTPServer

Это уже полноценный web-сервер, способный обрабатывать GET и POST-запросы, возвращать разные данные и пр. Но и кода разумеется, понадобится больше.

Рассмотрим минимально работающий вариант сервера:

Запускаем браузер, и видим в нем нашу HTML-страницу:

Данный сервер несложно научить отдавать файлы, например изображения.

Добавим в HTML тег img:

Исходный файл «raspberrypi.jpg» разумеется, должен лежать в папке с программой. Добавим в функцию do_GET возможность получения файлов:

Запускаем сервер, и видим соответствующую картинку:

Вряд ли такой сервер выиграет конкурс веб-дизайна, но он вполне работает. Сервер несложно заставить отдавать более полезные данные, например возвращать информацию о работе программы. Для примера добавим обработчик для новой функции status:

Теперь мы можем открыть в браузере ссылку http://192.168.1.102:5000/status и увидеть текущие параметры системы:

Кстати, как можно видеть, мы отдаем данные в формате JSON, что позволит использовать их для каких-то других запросов.

Заключение

Все задуманное в одну часть не влезло. Вторая часть доступна по ссылке.

Важно: меры безопасности

Если для Raspberry Pi будет использоваться внешний IP-адрес, обязательно стоит помнить о мерах безопасности. Может показаться что ваш мини-сервер никому не нужен, однако сейчас не составляет труда пакетно просканировать все диапазоны IP-адресов (как пример, Украина, Австрия) и найти все доступные устройства. Так что обязательно стоит поменять пароль на Raspberry Pi, и не стоит хранить на устройстве какую-либо конфиденциальную информацию (папки Dropbox, имена/пароли захардкоженные в скриптах, фото и пр).

Источник

5 способов сделать Python-сервер на Raspberry Pi. Часть 2

Сегодня мы продолжим изучать сетевые возможности Raspberry Pi, а точнее их реализацию на языке Python. В первой части мы рассмотрели базовые функции простейшего веб-сервера, работающего на Raspberry Pi. Сейчас мы пойдем дальше, и рассмотрим несколько способов, как сделать наш сервер интерактивным.

Статья рассчитана для начинающих.

Перед началом пара примечаний.

Во-первых, я и сам сомневался, стоит ли делать продолжение и ожидал больший поток критики и низких оценок, но как показал опрос в первой части, 85% читателей нашли приведенную там информацию полезной. Понимаю, что некоторых профи статьи «для чайников» раздражают, но все когда-то начинали, так что придется потерпеть.

Во-вторых, я буду писать про программирование, а не про администрирование. Так что вопросы настройки Raspbian, конфигов, VPN, безопасности и прочего, здесь рассматриваться не будут. Хотя это тоже важно, но нельзя объять необъятное. Здесь будет только про Python, и как сделать сервер на нем.

Кому все это неинтересно, могут нажать кнопку back в браузере прямо сейчас и не тратить свое ценное время ;)

Напомню, в предыдущей части мы закончили на том, что запустили на Raspberry Pi простой веб-сервер, показывающий статическую страницу:

Сейчас мы пойдем дальше, и сделаем наш сервер интерактивным, добавим на веб-страницу управление светодиодом. Разумеется, вместо светодиода может быть любое другое устройство, способное управляться от GPIO, но со светодиодом провести опыт проще всего.

Подготовка

Я не буду расписывать, как подключить светодиод к Raspberry Pi, желающие могут найти это в гугле за 5 минут. Напишем сразу несколько функций для использования GPIO, которые мы потом вставим в наш сервер.

Как можно видеть, каждая функция обращения к GPIO «обернута» в блок try-catch. Зачем это сделано? Это позволяет отлаживать сервер на любом ПК, включая Windows, что достаточно удобно. Теперь мы можем вставить эти функции в код веб-сервера.

Наша задача — добавить на веб-страницу кнопки, позволяющие из браузера управлять светодиодом. Будут рассмотрены 3 способа реализации.

Способ 1: Неправильный

Этот способ нельзя назвать красивым, зато он короткий и наиболее простой для понимания.

Создадим строку с HTML-страницей.

Здесь можно отметить 3 момента:

    Мы используем CSS для указания стиля кнопок. Это можно было бы и не делать и обойтись всего 4 строчками HTML-кода, но тогда наша страница выглядела бы как «привет из 90х»:

  • Для каждой кнопки мы создаем локальную ссылку типа /led/on и /led/off
  • Смешивать ресурсы и код это плохой стиль программирования, и в идеале, HTML лучше хранить отдельно от кода на Python. Но моя цель — показать минимально работающий код, в котором минимум лишнего, так что некоторые вещи для простоты опущены. К тому же, это удобно, когда код можно просто скопировать из статьи, без лишней возни с дополнительными файлами.
  • Сам сервер мы уже рассматривали в предыдущей части, осталось добавить в него обработку строк ‘/led/on’ и ‘/led/off’. Обновленный код целиком:

    Запускаем, и если все было сделано правильно, то мы можем управлять светодиодом через наш веб-сервер:

    Тестировать сервер можно не только на Raspberry Pi, но и на Windows или OSX, в консоли будут сообщения LED ON, LED OFF при нажатии на соответствующую кнопку:

    Теперь выясним, чем же этот способ плох, и почему он «неправильный». Этот пример вполне рабочий, и довольно часто копируется в разных туториалах. Но проблем тут две — во-первых, это неправильно перезагружать страницу целиком, когда мы лишь хотим зажечь светодиод. Но это еще полпроблемы. Вторая, и более серьезная, проблема в том, что когда мы нажимаем кнопку включения светодиода, адрес страницы становится http://192.168.1.106:8000/led/on. Браузеры обычно запоминают последнюю открытую страницу, и при последующем открытии браузера команда включения светодиода сработает еще раз, даже если мы этого не хотели. Поэтому мы перейдем к следующему, более правильному способу.

    Способ 2: Правильный

    Чтобы сделать все правильно, вынесем функции включения и выключения светодиода в отдельные запросы, а вызывать их будем асинхронно с помощью Javascript. Код HTML страницы теперь будет выглядеть так:

    Как можно видеть, мы отказались от href, и вызываем функции ledOn и ledOff, которые в свою очередь, асинхронно вызывают соответствующие методы сервера (асинхронные методы нужны для того, чтобы страница не блокировалась, пока ответ от сервера не пришел).

    Теперь осталось добавить на сервер обработку get-запросов:

    Теперь, как можно видеть, страница уже не перезагружается при попытке зажечь светодиод, каждый метод делает только то, что и должен делать.

    Способ 3: Более правильный

    Вроде бы все уже работает. Но разумеется, приведенный код можно (и нужно) улучшить. Дело в том, что для управления светодиодом мы используем GET-запросы. Это экономит нам место в коде, но методологически это не совсем правильно — GET-запросы предназначены для чтения данных с сервера, они могут кешироваться браузером, и вообще говоря, не должны использоваться для изменения данных. Правильный способ — это использовать POST (для тех, кому интересны детали, подробнее тут).

    Поменяем вызовы в HTML с get на post, ну а заодно, раз уж код у нас асинхронный, выведем статус ожидания ответа сервера и отображения результатов работы. Для локальной сети это заметно не будет, но для медленного соединения весьма удобно. Чтобы было интереснее, для передачи параметров будем использовать JSON.

    Окончательный вариант выглядит так:

    Добавим в сервер поддержку GET и POST запросов:

    Как можно видеть, мы теперь используем одну функцию led, в которую с помощью json передается параметр «on», принимающий True или False (при вызове в HTML передается соответственно json-строка вида < «on»: true >). Также стоит обратить внимание на try-catch — это блокирует сервер от «падения», например, если кто-то пошлет строку с невалидным json на сервер.

    Если все было сделано правильно, мы получаем сервер с обратной связью, который должен выглядеть примерно так:

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

    Можно ли этот сервер еще улучшить? Можно, например имеет смысл заменить использование функции print на использование logging, это более правильно, и позволяет выводить логи сервера не только на экран, но и при желании писать их в файл с автоматической ротацией. Желающие могут заняться этим самостоятельно.

    Заключение

    Если все было сделано правильно, мы получим мини-сервер, позволяющий управлять светодиодом или любым другим устройством через браузер с любого устройства сети.

    Важно: Меры безопасности

    Еще раз отмечу, что никакой защиты или аутентификации тут нет, так что не стоит «выкладывать» такую страницу в Интернет, если планируется управлять какой-то более-менее ответственной нагрузкой. Хотя случаи атак на подобные серверы мне неизвестны, но все же не стоит давать любому желающему возможность удаленно открыть дверь гаража или включить киловаттный обогреватель. При желании удаленного управления через такую страницу, стоит настроить VPN или что-то аналогичное.

    В завершение повторюсь, что материал расчитан для начинающих, и надеюсь, это было более-менее полезно. Понятно, что не все на Хабре довольны наличием статей «для чайников», так что будет или нет следующая часть, будет зависеть от итоговых оценок. Если будет, то в ней будут рассмотрены фреймворки Flask и WSGI, так же будут рассмотрены базовые методы аутентификации.

    Источник

    Adblock
    detector