Статьи

Рецепт для мRuby Raspberry Pi? Просто добавьте воду!

IoTWeek_Gray

Это неделя Интернета вещей в SitePoint! Всю неделю мы публикуем статьи, ориентированные на пересечение интернета и физического мира, поэтому следите за последними обновлениями в теге IoT .

Когда отличные ребята из SitePoint рассказали мне о IoT Week и сказали, что мне нужно сгенерировать пару сообщений IoT, связанных с Ruby, я воспринял это как знак. Пару месяцев назад я купил Raspberry Pi 3, и с тех пор он собирает цифровую пыль. Он сидит на столе рядом с моим ботаником и издевается надо мной.

«Эй, Гленн, помнишь, когда ты купил меня? Я все еще здесь … ты можешь хотя бы использовать меня как подставку или что-то в этом роде?

Каждый день мне приходилось сталкиваться с позором своего ботаника перед лицом этого неиспользованного маяка моего бездействия.

Ну не надо больше! IoT Week предложила мне руку, чтобы побороть мой позор и, наконец, использовать мой Raspberry Pi. Мне больше не придется задумываться о том, чтобы сдать карту Nerd и искать работу в качестве мега-магазина.

По правде говоря, одним из главных мотивов покупки Raspberry Pi было «делать вещи» с моими детьми. Несколько моих детей (у меня их так много) проявили склонность к программированию и другим увлечениям, поэтому я решила, что RPi была отличной платформой для полива этих семян. Тем не менее, когда дело доходит до Raspberry Pi, я просто садовник-любитель. Поэтому я использую IoT Week и этот пост как шанс познакомиться с Raspberry Pi.

На этом примечании может быть отказ от ответственности. Я новичок в RPi и встроенных системах в целом. Вредить на этих платформах часто приходится при компиляции библиотек на Си и других вещей, о которых я давно забыл все, что когда-то знал. Итак, этот пост и все, что в нем написано, работает просто. И, за то, что это стоит, у меня были некоторые проблемы.

Хорошо, этого достаточно для меня и моих недостатков. Давай зайдем.

цели

Одна из моих долгосрочных целей для RPi — сделать один из тех визуальных дверных звонков, которые вы можете купить за $ 129. Эти устройства позволяют вам использовать приложение, чтобы видеть, кто у вас за дверью, в том числе возможность разговаривать с ними и т. Д. Теперь, прежде чем вы будете взволнованы и думаете, что этот пост покажет вам, как сделать один из них, не т. Я расскажу лишь о нескольких аспектах того, что, по моему мнению, составит конечный продукт.

Первое, на что я остановлюсь, — это возможность передавать изображения с RPi и видеть их в браузере. Дверной звонок должен будет сделать это, очевидно, так что это хорошее место для начала.

Цель № 2 — обслуживать простой API от RPi. Мой дверной звонок должен будет собирать и обслуживать данные, а также выполнять другие функции API / микросервис / блестящие игрушки, так что это окажется основой для моих долгосрочных усилий.

Оборудование

Вкратце, давайте пройдемся по оборудованию:

оборудование

Чтобы начать свои RPI крестовые походы, я купил следующее:

  • Raspberry Pi 3
  • 5 В блок питания
  • Raspberry Pi Модуль камеры
  • Дерзкий красный Raspberry Pi чехол
  • Карта памяти microSD 64 ГБ. Я думаю, что это должен быть класс 10 или выше, поэтому убедитесь, что получили правильные вещи. Вы можете купить карты microSD, уже установленные с NOOBS, о которых я расскажу в следующем разделе.

Если вам нужно приобрести эти предметы, мне очень повезло с MCM Electronics и Pololu.com .

Затем из моего постоянно растущего тайника с ботаником я поставил:

  • USB-клавиатура
  • USB-мышь
  • Монитор с поддержкой HDMI

Програмное обеспечение

Видя, как это сообщение на канале SitePoint Ruby, я попытаюсь использовать некоторые инструменты Ruby для достижения своих целей. Я начал исследования для этой статьи с поиска Ruby, встроенных систем и тому подобного. Это почти сразу привело меня к mRuby , который я видел в нескольких постах за время моей работы в качестве редактора. По правде говоря, я не был уверен, что такое mRuby и как его использовать. Фактически, в какой-то момент я подумал, что это просто урезанный интерпретатор Ruby с небольшим размером. Это заняло написание этого поста, чтобы научить меня, что он встроен в другие программы и т. Д. То есть mRuby встроен в другую программу, чтобы обеспечить обработку Ruby для этой программы. То, что мы делаем сегодня в этом посте, должно привести к этому.

Операционная система

Для операционной системы я выбрал Raspbian, так как это «стандартная» операционная система RPi. Я упомянул выше NOOBS , который вы можете приобрести предустановленным на карту microSD. NOOBS поставляется с несколькими вариантами ОС, и вы выбираете один из них при загрузке RPi. Если вы пошли по этому пути, выберите Raspbian, и все готово.

Другой вариант — установить NOOBS (или другую ОС) на чистую карту microSD, что я и пытался сделать. На четыре часа. Я не смог заставить RPI загружаться с этой карты, поэтому я выполнил указание и установил Raspbian прямо на карту с помощью этих инструкций . Это отлично сработало, и я мог загрузить RPi:

рабочий стол

Raspbian поставляется с Ruby 2.1.5, что достаточно для наших нужд сегодня. Кроме того, в большинстве инструкций RPi рекомендуется запускать raspi-config и расширять файловую систему для использования всей вашей карты. Я также использовал raspi-config чтобы выбрать правильную локаль и клавиатуру. Если при вводе вы видите странное поведение, например, при вводе $ показывает £ (или наоборот, в зависимости от того, что вы хотите), то вам, вероятно, нужно изменить локаль и клавиатуру.

Как я уже упоминал, я хочу создать API и делать снимки с камеры, открывая оба браузера. Для этого требуется какой-то веб-сервер. Сочетание потребности моего веб-сервера с моим желанием использовать mRuby привело меня к идеальному программному обеспечению: веб-серверу h2o . h2o утверждает, что является более быстрым веб-сервером, который использует меньше ресурсов процессора и в полной мере использует все преимущества HTTP / 2. Кроме того, и мне не стыдно признать, что я немного визжал, когда читал это: h2o использует mRuby, предоставляя возможность писать обработчики с Ruby! Как будто авторы знали, что я в конце концов напишу этот пост! Ура!

Настройка H2O

К счастью, другие прошли через шаги, чтобы настроить H2O на Raspberry Pi. Я упомянул два таких поста в своем исследовании:

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

 $ sudo apt-get update $ sudo apt-get install -y build-essential cmake bison git 

Это установит запрошенные пункты. Мы должны быть хороши, чтобы установить H2O сейчас:

 $ git clone https://github.com/h2o/h2o.git $ cd h2o $ cmake -DCMAKE_C_FLAGS_RELEASE= \ -DCMAKE_CXX_FLAGS_RELEASE= \ -DCMAKE_INSTALL_PREFIX=./dist \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_FIND_FRAMEWORK=LAST \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -Wno-dev $ make $ make install 

Шаг make занимает некоторое время, просто чтобы вы знали.

Конфигурирование h2o — это простой вопрос создания или YAML и запуска двоичного файла h2o. Вот пример файла конфигурации h2o, который называется h2o.conf и находится в каталоге h2o:

 listen: 8080 hosts: "localhost:8080": paths: /api: file.dir: . mruby.handler-file: json_api.rb 

Этот файл скажет h2o прослушивать порт 8080 и предоставить конечную точку /api которая поддерживается моим обработчиком Ruby, в файле с именем json_api.rb . Обработчик Ruby, в данном случае, это просто приложение Rack, как показано в этом файле, украденном из сообщения Боунги:

 class JsonApi def initialize @storage = {foo: "bar"} end def call(env) body = JSON.generate({foo: @storage[:foo]}) [ 200, {'Content-Type' => 'application/json', 'Content-Length' => body.size}, [body] ] end end JsonApi.new 

При наличии файла конфигурации и обработчика запуск сервера h2o так же прост, как:

 dist/bin/h2o --conf h2o.conf 

и посещение конечной точки, которая в данном случае является http: // localhost: 8080 / api

 curl http://localhost:8080/api/ {"foo":"bar"} 

Поздравляем! Теперь вы официальный пользователь mRuby.

Цель № 1: захват фотографий

Чтобы сделать снимки, я собираюсь использовать команду ОС, которую я обнаружил, когда тестировал установку модуля камеры, которая называется raspistill . Кстати, вы должны установить свой модуль камеры на RPi. Теперь, чтобы захватить изображение с камеры, введите следующее:

 raspistill -o image.png 

Вы должны увидеть всплывающее окно на экране и в конечном итоге уйти (это окно «предварительного просмотра»), указывающее, что изображение захвачено. Откройте файл, и вы увидите что-то вроде:

захватить

Примечание. Ваша фотография, несомненно, будет более привлекательной.

Итак, у нас есть системная команда, которую мы можем использовать для захвата изображения с камеры. Теперь нам просто нужно вызвать его из обработчика Ruby:

 class PicApi def call(env) file = capture [ 200, {'Content-Type' => 'image/jpeg', 'Content-Length' => File.size(file)}, file ] end private def capture fn = Time.now.to_i.to_s `raspistill -n -o /tmp/#{fn}.jpg` File.open("/tmp/#{fn}.jpg") end end PicApi.new 

Это очень просто. Я фиксирую файл, используя raspistill (если вы не знали, обратные raspistill системную команду в Ruby), как мы делали выше. Разница в расположении и параметре. Я записываю файл (имя, основанное на текущем времени) в каталог /tmp чтобы он в конечном итоге был перекрыт, и я использую параметр -n чтобы пропустить экран предварительного просмотра. Когда у нас есть файл, его открытие с помощью File.open возвращает объект File , который отвечает each соответствии со спецификацией Rack. Я был очень взволнован, когда обнаружил, как легко это было. Все это действительно помогло мне поместить mRuby в его законное место в моем мозгу и заставило меня чувствовать себя довольно крепким ботаником.

Когда обработчик готов, его нужно добавить в файл конфигурации h2o ( h2o.conf ):

 listen: 8080 hosts: "localhost:8080": paths: /: file.dir: . /api: file.dir: . mruby.handler-file: json_api.rb /pic: file.dir: . mruby.handler-file: pic_api.rb access-log: /dev/null 

Теперь из каталога h2o:

 dist/bin/h2o --conf h2o.conf 

Если вы откроете http: // localhost: 8080 / pic , захваченное изображение станет вашей наградой!

Цель № 2: API

В двух сообщениях о h2o, на которые я ссылаюсь выше, есть примеры того, как создать базовый обработчик API для h2o. Поэтому мне нужно сделать что-то другое, чтобы добавить знания, а не просто перерабатывать их. Я собираюсь пройтись по добавлению поддержки PostgreSQL во встроенную установку mRuby и продемонстрировать, как подключиться к PostgreSQL. На мой взгляд, реальная выгода здесь — это еще один пример добавления возможностей для mRuby и h2o, наряду с упоминанием того, где я наткнулся на этом пути.

Во-первых, самая простая часть: поскольку Ruby — это невероятное сообщество, кто-то уже создал привязки mRuby для PostgreSQL . Нам просто нужно добавить его в mRuby. Сообщение Луки делает то же самое для Hiredis, и шаги:

Клон репо

Клонируйте соответствующий репозиторий git в папку deps / в каталоге h2o. В этом случае я клонировал этот .

Скомпилировать воду

Скомпилируйте h2o, используя ту же команду cmake сверху. Однако я застрял здесь на несколько часов . Это где мой C noobage чуть не убил все мои моджо. При сборке h2o одним из созданных артефактов является каталог mruby / с скомпилированной версией mRuby. В последующих сборках, если этот каталог существует, mRuby не перестраивается, поэтому любые новые deps не будут скомпилированы в двоичный файл. Я не осознавал этого, к моему большому стыду. Итак, если у вас есть каталог mRuby / в вашем каталоге h2o (примечание: я НЕ говорю о deps / mruby ), удалите его и запустите:

 cmake -DCMAKE_C_FLAGS_RELEASE= \ -DCMAKE_CXX_FLAGS_RELEASE= \ -DCMAKE_INSTALL_PREFIX=./dist \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_FIND_FRAMEWORK=LAST \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -Wno-dev 

Создайте обработчик Ruby

Создайте свой новый обработчик. Я создал файл с именем pg_api.rb, который выглядит следующим образом:

 class PgApi def initialize @conn = PG::Connection.new(host: '192.168.1.52', port: 5432, dbname: 'mydb', user:'myuser', password:'mypassword') end def call(env) body = get_data [ 200, {'Content-Type' => 'application/json', 'Content-Length' => body.size }, body ] end private def get_data json = [] @conn.exec("select * from accounts") do |result| json << { email: result["email"], created_at: result["created_at"] } end json end end PgApi.new 

Используя mruby-pg PG::Connection , я создал соединение с экземпляром PostgreSQL, работающим в другом месте моей сети. Если у вас нет доступа к такой вещи, я рекомендую использовать Docker, чтобы поместить ее в ящик в вашей сети. Это очень легко.

Настройте h2o для использования обработчика

Добавьте новый обработчик в конфигурацию h2o:

 listen: 8080 hosts: "localhost:8080": paths: /: file.dir: . /api: file.dir: . mruby.handler-file: json_api.rb /pic: file.dir: . mruby.handler-file: pic_api.rb /pg: file.dir: . mruby.handler-file: pg_api.rb access-log: /dev/null 

Это старая шляпа сейчас. Просто добавьте конечную точку /pg которая указывает на наш обработчик Ruby, и перезапустите h2o.

 dist/bin/h2o --conf h2o.conf 

Если вы посетите http: // localhost: 8080 / pg / , вы увидите результат вашего оператора SQL select в форме JSON. мммммммРуби… это хороший RPi.

Как вы можете видеть, я мог бы создать любой JSON API, который пожелал, при поддержке PostgreSQL. Для практики вы должны попробовать это с другой базой данных, такой как MongoDB или MySQL.

Вывод

Ну, я достиг своих двух целей. Я могу захватывать изображения с камеры и открывать их в браузере, а также публиковать API, поддерживаемый базой данных PostgreSQL. Возможно, не самые амбициозные цели в мире, но они являются основополагающими для меня и моих конечных целей. Один из моих следующих шагов — захват живого видео … Я слышал, что uv4l хорош для этого …

Я надеюсь, что вы получили что-то из этого поста и теперь вдохновлены, чтобы взломать Raspberry Pi и mRuby. Если вы хотите мой совет, просто добавьте воду…