httpを用いたデバイス制御 の変更点
更新- 追加された行はこの色です。
- 削除された行はこの色です。
- 電気回路/zynq/httpを用いたデバイス制御 へ行く。
- 電気回路/zynq/httpを用いたデバイス制御 の差分を削除
[[電気回路/zynq]] * 概要 [#s41f0955] ブラウザや Web API を使って http または https 経由でデバイスを制御したい。 - ブラウザから Web Form でレジスタをいじる - Lab View などから Web API を叩いてレジスタをいじる ** 目次 [#ff916303] #contents * Web アプリのフレームワークに Sinatra を使う [#u717b5cd] いろいろ考えられるけれど、ここでは ruby 製の Sinatra を使ってみる。 - http://sinatrarb.com/ 理由は自分が ruby とか Rails とかに慣れていることと、Rails ほど重厚なフレームワークは必要ないこと。 ruby 製の簡易Webサーバーで動くため、apache や nginx を導入することなく使える。 * ruby のセットアップ [#kc961b46] zynq の Ubuntu 18.04LTS に rvm を入れて、そこから ruby や各種 gem を準備する。 https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-with-rvm-on-ubuntu-18-04 LANG:console $ # install rvm $ sudo apt-get install -y gnupg2 $ gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB $ cd /tmp $ curl -sSL https://get.rvm.io -o rvm.sh $ cat rvm.sh | bash -s stable $ source ~/.rvm/scripts/rvm $ rvm list known # MRI Rubies [ruby-]1.8.6[-p420] [ruby-]1.8.7[-head] # security released on head [ruby-]1.9.1[-p431] [ruby-]1.9.2[-p330] [ruby-]1.9.3[-p551] [ruby-]2.0.0[-p648] [ruby-]2.1[.10] [ruby-]2.2[.10] [ruby-]2.3[.8] [ruby-]2.4[.5] [ruby-]2.5[.3] [ruby-]2.6[.0] ruby-head ... $ rvm install 2.6 # ruby 2.6 のインストール → かなり時間がかかる $ which ruby /home/takeuchi/.rvm/rubies/ruby-2.6.0/bin/ruby $ ruby --version ruby 2.6.0p0 (2018-12-25 revision 66547) [armv7l-linux-eabihf] * Sinatra を使う [#b4acd73e] LANG:console $ mkdir ~/sinatra_app $ cd ~/sinatra_app $ git init $ # rvm の自動切り替え設定 $ echo 2.6 > .ruby-version $ echo sinatra_app > .ruby-gemset $ cd . ruby-2.6.0 - #gemset created /home/takeuchi/.rvm/gems/ruby-2.6.0@sinatra_app ruby-2.6.0 - #generating sinatra_app wrappers......... $ # bundler を使って Gemfile で gem を管理する $ gem install bundler $ bundle init $ cat Gemfile # frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } # gem "rails" $ git add . $ git config --global user.email "takeuchi@bk.tsukuba.ac.jp" $ git config --global user.name "Osamu Takeuchi" $ git commit -m "start development" $ # Sinatra のインストール $ cat << EOT >> Gemfile gem "sinatra" gem "sinatra-contrib" EOT $ bundle install $ # Hello, world! アプリの作成 $ cat << EOT > app.rb require "sinatra" require "sinatra/reloader" get "/" do "Hello, world!\n" end EOT $ bundle exec ruby app.rb & [2019-03-28 08:29:29] INFO WEBrick 1.4.2 [2019-03-28 08:29:29] INFO ruby 2.6.0 (2018-12-25) [armv7l-linux-eabihf] == Sinatra (v2.0.5) has taken the stage on 4567 for development with backup from WEBrick [2019-03-28 08:29:29] INFO WEBrick::HTTPServer#start: pid=14700 port=4567 $ curl http://localhost:4567/ Hello, world! $ fg ^C $ git add . $ git commit -m "hello world!" * 外部へ公開する [#i822ce3c] どうやら動いているみたいだけれど、 ホストPCのブラウザから zynq 機器の IP アドレスを指定して http://xxx.xxx.xxx.xxx:4567/ へアクセスしても、 「正常に接続できませんでした」と言われた。 はじめ、ファイアーウォールのせいかと勘違いしたのだけれど、 実は今の手順でビルドした Kernel には iptable の機能が 備わっておらず、ファイアーウォールなんて影も形もない状態だった。 で気づいたのは、zynq のコンソールからでも 127.0.0.1 以外の IP アドレスを指定すると LANG:console $ curl http://192.168.2.2:4567/ # 自分のアドレス curl: (7) Failed to connect to 192.168.2.2 port 4567: Connection refused のように弾かれるのだった。これは、127.0.0.1 しか listen していない感じ。 LANG:console $ ruby app.rb --help Usage: app [options] -p port set the port (default is 4567) -o addr set the host (default is localhost) -e env set the environment (default is development) -s server specify rack server/handler (default is thin) -q turn on quiet mode (default is off) -x turn on the mutex lock (default is off) $ ruby app.rb -o 0.0.0.0 & $ curl http://192.168.2.2:4567/ Hello, world! これで外部からも繋がるようになった。 ただし、ポートを 80 番にしようとすると Permission Denied と言われる。 Well known port にサーバーを建てるには sudo が必要。 加えて環境変数の読み込みも必要。 LANG:console $ ruby app.rb -p 80 /home/takeuchi/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/socket.rb:201:in `bind': Permission denied - bind(2) for 127.0.0.1:80 (Errno::EACCES) $ sudo bash -c "source /home/takeuchi/.rvm/scripts/rvm;ruby app.rb -o 0.0.0.0 -p 80" (うまくいく) 開発が終わり実用段階へ到達したら -e production なども付けたいところ。 * erb テンプレートを使う [#p50fc0f4] app.rb LANG:rb require "sinatra" require "sinatra/reloader" get "/" do erb :index end views/index.erb LANG:erb Hello, world from erb! として、 LANG:console $ curl http://192.168.2.2/ Hello, world from erb! $ git add . $ git commit -m "hello from erb" * layout を使う [#l643e96d] - 個々に指定した出力が layout.erb の yield の部分にはめ込まれる。 - @title のような変数を view 側と共有できる app.rb LANG:rb require "sinatra" require "sinatra/reloader" get "/" do @title = "Device Editor" erb :index end views/layout.erb LANG:erb <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <title><%= @title %></title> </head> <body> <h1><%= @title %></h1> <%= yield %> </body> </html> LANG:console $ curl http://192.168.2.2/ <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <title>Device Editor</title> </head> <body> <h1>Device Editor</h1> Hello, world from erb! </body> </html> $ git add . $ git commit -m "layout introduced" * フォームを作成 [#m9611d1f] erb から uio コマンドを呼び出し、得られたレジスタ値をフォームの input に表示する。 app.rb LANG:ruby require "sinatra" require "sinatra/reloader" get "/" do @title = "Device Editor" @regs = [ # 表示名 name値 値の読取コマンド ["Reg 01", "reg1", "uio 0 0 "], ["Reg 02", "reg2", "uio 0 4 "], ["Reg 03", "reg3", "uio 0 8 "], ["Reg 04", "reg4", "uio 0 12 "], ] erb :index end views/index.erb LANG:erb <form method="post"> <% @regs.each do |reg| %> <div class="field"> <label class="label"><%= reg[0] %> <div class="control"> <input class="input" type="text" placeholder="<%= reg[0]%>" name="<%= reg[1]%>" value="<%= `#{reg[2]}` %>"> </div> </label> </div> <% end %> <div class="field"> <div class="control"> <button class="button is-primary">Submit</button> </div> </div> </form> ブラウザから読みに行けば、フォームにレジスタの現在値が表示される。 &ref(default-form.png,,50%); LANG:console $ git add . $ git commit -m "device editor form created" * スタイルシートを適用する [#n10145ff] Bulma ( https://bulma.io/ ) という css フレームワークを使ってみる。 - [[知っておくと少し幸せになれるBulmaを使い方6選>https://tonyo.design/program/bulma/good_6_things_to_know_about_bluma/]] layout に - viewport 指定 - css への link - font awsome の script 読み込み - yield を section, container で囲む - h1 に .title を付ける の変更を行った。 views/layout.erb LANG:erb <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><%= @title %></title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css"> <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script> </head> <body> <section class="section"> <div class="container"> <h1 class="title"> <%= @title %> </h1> <%= yield %> </div> </section> </body> </html> フォームの html は何も変更していないが、ちゃんと今風の表示になった。 &ref(form-styled.png,,50%); LANG:console $ git add . $ git commit -m "style sheet applied" * フォームによる値の変更を反映する [#v1759dd6] 上記のフォームで Submit ボタンを押すと、 Try this: post '/' do "Hello World" end が表示される。 フォームの書き換えでは自身のアドレス "/" に対して POST が生じるのだ。 そこで app.rb を、 LANG:rb require "sinatra" require "sinatra/reloader" REGS = [ ["Reg 01", "reg1", "uio 0 0 "], ["Reg 02", "reg2", "uio 0 4 "], ["Reg 03", "reg3", "uio 0 8 "], ["Reg 04", "reg4", "uio 0 12 "], ] get "/" do @title = "Device Editor" @regs = REGS.clone erb :index end post "/" do @title = "Device Editor" @regs = REGS.clone @regs.each do |reg| if params.has_key? reg[1] begin value = Integer(params[reg[1]]) system reg[2] + value.to_s # 値を書き込む system reg[2] + value.to_s # 値を書き込む(http からの値を system にそのまま渡すとか、超危険なので絶対真似しちゃダメ) rescue reg[3] = "error" end end end erb :index end とすることで、レジスタ値を変更することが可能になった。 LANG:console $ git add app.rb $ git commit -m "post requiest is handled" * SSL 化する? [#me8cda8f] - https://qiita.com/k-ta-yamada/items/a8a50bd6e75e08c802dc - https://stackoverflow.com/questions/3696558/how-to-make-sinatra-work-over-https-ssl Lab View からのアクセスを考えると、むやみに SSL 化しない方が使いやすいかも。 どちらにしても LAN 内にしか公開しないし。 * 認証 [#fe47dab0] こちらはすべきかなあ。 https://qiita.com/hiroki_y/items/06f5780543bec988d8b7#basic%E8%AA%8D%E8%A8%BC まあ、しばらくはなしでも。 * 自動起動 [#z6271ba5] とにかく起動するだけだけれど、以下のようにして行えた。 Webrick をデバッグモードで外向きに建てるとか 本来はあり得ないのでしょうけれど、 とりあえず開発用ということで、 しばらくはこのままいく。 https://blog.freedom-man.com/start-stop-daemon/ /boot/fpga_init.d/99_sinatra_app LANG:sh #!/bin/bash . /lib/lsb/init-functions PIDFILE=/home/takeuchi/sinatra_app/app.pid do_start () { cd /home/takeuchi/sinatra_app . /home/takeuchi/.rvm/scripts/rvm DAEMON=`which ruby` DAEMON_ARGS="/home/takeuchi/sinatra_app/app.rb -o 0.0.0.0 -p 80" echo -n "starting sinatra_app..." start-stop-daemon --start --background --exec $DAEMON --make-pidfile --pidfile $PIDFILE -- $DAEMON_ARGS result=$? if [ $result != "0" ]; then pid=`cat $PIDFILE` echo "daemon is already running. (pid=${pid})" exit 1 else echo fi } do_stop () { echo -n "stopping sinatra_app..." start-stop-daemon --stop --pidfile $PIDFILE result=$? if [ $result != "0" ]; then pid=`cat $PIDFILE` echo "daemon is not running. (check $PIDFILE)" exit 1 else echo fi rm -f $PIDFILE } case $1 in start) do_start ;; stop) do_stop ;; *) echo "Usage: $0 {start|stop}" exit 2 ;; esac 作業履歴へ戻る → [[電気回路/zynq]] * コメント・質問 [#n4ea9bc6] #article_kcaptcha
Counter: 3005 (from 2010/06/03),
today: 1,
yesterday: 1