Status Code 303 - See Other

サーバサイド、iOS・アンドロイドアプリ、インフラレベルの話まで幅広くやってます。情報の誤りや指摘・意見などは自由にどうぞ。

RaspberryPi に Rest API を簡単に実装

概要

Raspberry Pi に対して情報を取得する際に HTTPを利用してこれを行いたい場合がある。
ruby のウェブフレームワークで有名なのは、Rails だが、Rails は大規模向けであるため
簡素な実装をするにも、構築時間、学習コストが見合わないことがある。
今回は ruby 初心者でも手軽に実装できる、軽量フレームワークSinatraを導入し、Rest APIを実装してみた。

Sinatra 導入

ruby, gem 導入

このあたりで多分導入できる(はず)。
Raspberry piにRubyの最新版をインストールする - Qiita
なお、自身のRaspberryPiにはすでにインストールされていたため、実施していません。
バージョン関連の情報は以下。

$ ruby -v
ruby 2.1.5p273 (2014-11-13) [arm-linux-gnueabihf]
$ gem -v
2.2.2

Sinatra 導入

参考:Sinatra: README (Japanese)

基本的に下記コマンドを実行するだけ。

$ sudo gem install sinatra
$ sudo gem install thin

URI、コンテンツ定義

以下のファイルをどこでもいいので、作成する。(下記を app.rb として保存する)

require 'sinatra'
set :bind, '0.0.0.0' # これを書くと http://localhost:4567 以外からでもアクセス可能。

get '/' do # ルートに GET でアクセスした場合
  "Top!\n" # 返却する内容
end
get '/:name' do |n| # /{name} GET でアクセスした場合
  "Hello #{n}\n"    # {name}の部分を値として使う
end

サーバ起動

$ ruby app.rb

アクセス

※ 192.168.0.30 はRaspberrypiのプライベートアドレス
http://192.168.0.30:4567/
f:id:kouki_hoshi:20160911233644p:plain
http://192.168.0.30:4567/aaa
f:id:kouki_hoshi:20160911233938p:plain

実装例

これだけであれば、インストール除けば5分で作成可能。
メモリとディスクのプロパティを入手する API を作ってみた。

require 'sinatra'
require 'json'

set :bind, '0.0.0.0'

disk = Struct.new("Disk", :name, :path, :total, :used)
get '/disk' do
  disks = `df -l | sed -e "1d"`.split("\n").inject([]) do |list, line|
    arr = line.split("\s")
    list << disk.new(arr[0], arr[5], arr[3].to_i, arr[2].to_i).to_h
  end
  JSON.generate({"disks" => disks})
end

memory = Struct.new("Memory", :total, :used, :free, :shared, :buffers, :cached)
get '/memory' do
  arr = `free | sed -n -e "2p"`.split("\s")
  mem = memory.new(arr[1].to_i, arr[2].to_i, arr[3].to_i, arr[4].to_i, arr[5].to_i, arr[6].to_i)
  JSON.generate(mem.to_h)
end

Cygwin 上で curl 実行できれば、下記コマンドでいける。

$ curl http://192.168.0.30:4567/disk | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   580  100   580    0     0   3505      0 --:--:-- --:--:-- --:--:--  3602
{
  "disks": [
    {
      "name": "/dev/root",
      "path": "/",
      "total": 22113944,
      "used": 6837300
    },
    {
      "name": "/dev/sda1",
      "path": "/media/hdd1",
      "total": 455974524,
      "used": 177392
    },
  ]
}
$ curl http://192.168.0.30:4567/memory | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    91  100    91    0     0   1925      0 --:--:-- --:--:-- --:--:--  2166
{
  "total": 948012,
  "used": 879992,
  "free": 68020,
  "shared": 28708,
  "buffers": 206668,
  "cached": 267452
}

まとめ

テンプレート利用やルーティング条件などが設定できるため、ある程度難しいこともできそうだ。
もし、バックエンドでのみ使用する API であれば、製造コスト的に選択の一つとしてはいいかもしれない。