0

HTML+JavaScriptをArduinoに直結できるシリアルポートサーバーを作った

SerialPort Serverを使うと、HTMLとJSをArduinoに直結できる。JavaScriptを少し書くだけでArduinoに「カーテン開けろ」とか「部屋の明るさよこせ」とか命令を送れるわけだ。
Web系の技術とハードウェアの技術を同時に使うには、間に「つなぎ」が必要なので、必要な機能を全部入れたサーバーを作ってみた感じです。
(github pagesでプロジェクトページ作ってみたんだけど楽でいいですね)


こういうこと。


シリアルポートサーバーはrubygemsでインストールできる。

gem install serialport-server
which serialport-server
serialport-server --help
serialport-server /dev/tty.デバイス名
–helpでヘルプが出る。デバイス名を引数にして起動できる。
Macならsudo gem installで一発でインストールできるはず。

起動するとHTTPサーバー(http://localhost:8783)、WebSocketサーバー(ws://localhost:8784)、TCP Socketサーバー(localhost:8785)の3つが同時に起動する。

HTTPのサーバーはajaxのクロスドメイン制限を超えてデータのやりとりができるようにしてある。シリアルポートサーバーを動かして、HTMLとJavaScriptを書けばArduinoとJavaScriptが直接通信できるというわけだ。
(response headerにAccess-Control-Allow-Originを付ければ良いとyuisekiのはてブを見ていて知ったのでやってみた。)


■デモ
SerialPort Serverのページにも英語で書いたが、簡単なサンプルプロジェクトを日本語でも解説しておく。


1. Arduinoにプログラムを書き込む

2. ArduinoのDigital13番ピンにLEDを、Analog0番ピンにCdSと10kΩの抵抗を接続する
SerialPort Server sample
SerialPort Server sample

3. SerialPort Serverを起動する

4. Ajax版サンプルを開いて試してみる

5. WebSocket版サンプルを開いて試してみる


WebブラウザからLEDを点灯消灯したり、CdSの明るさの値がリアルタイムにスライダーに反映されているはずだ。
実際にAjaxサンプルのJavaScriptのコードを見てみると簡単さがわかると思う。17行でLEDとCdSを制御できている。



もちろんWebサーバーなので、複数のWebブラウザがSerialPort Serverから同時にデータを読み出そうとしても大丈夫。
増井研で1年以上、遠隔操縦ロボットの制御に使っていたプログラムを元に使っているのでプロセスを起動してたぶん3ヶ月ぐらい放置していても動き続けるぐらいに安定していると思う。

0

args_parserを使うとRubyでコマンドラインアプリ作るのにとても便利

args_parserというgemを作りました。
2年前に作ったArgsParserをバージョンアップしていたら互換性が無くなってきたので名前を変えた。
optparseよりもすっきり書けると思う。


■インストール

gem install args_parser


■使い方
試しに、「webページのURLを指定してダウンロードする」アプリを作ってみる。
こういう風に使えるのを作る。
ruby download_webpage.rb -url http://example.com -o out.html


download_webpage.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'args_parser'

parser = ArgsParser.parse ARGV do
arg :url, 'URL', :alias => :u
arg :output, 'output file', :alias => :o, :default => 'out.html'
arg :verbose, 'verbose mode'
arg :help, 'show help', :alias => :h
end

if parser.has_option? :help or !parser.has_param?(:url, :output)
STDERR.puts parser.help
STDERR.puts "e.g. ruby #{$0} -url http://example.com -o out.html"
exit 1
end

require 'open-uri'
puts 'download..' if parser[:verbose]
data = open(parser[:url]).read
puts data if parser[:verbose]

open(parser[:output], 'w+') do |f|
f.write data
end
puts "saved! => #{parser[:output]}"


こんな感じで実行できる。

0

Bundler.requireがエラー出すので、プロジェクトローカルにgemを入れた

とある環境でbundle installしてsystemにインストールされたrubygemを使う様にしたら、Bundler.requireがエラー出すようになった。

bundler-1.1.3/lib/bundler/runtime.rb:77:in `require': private method `gsub' called for nil:NilClass (NoMethodError)


プロジェクトローカルにインストールしたらエラーが出なくなった。
bundle install --path gems


■Bundler
最近はbundlerというgemの管理機構が使われている。

Gemfileというテキストファイルを作って、プロジェクトで使用するRubygemsを書いておく。

Gemfile
source :rubygems

gem 'sinatra', '>=1.3'
gem 'twitter'
gem 'oauth', '0.4.5'
gem 'json'
バージョン指定ができる。

bundle install
rubygemsに公開されていないgitリポジトリを指定したりもできるし、一発で全てのgemがインストールできるので開発環境から本番環境にデプロイするのに便利。
メジャーバージョンアップで仕様が大きく変わったgemがあっても問題ない。


require 'rubygems'
require 'bundler/setup'
Bundler.require
require 'yaml'
これでGemfileに書かれたgemがrequireされる。
yamlみたいな標準で入ってるgemは自分でrequireしないとならないっぽい。

0

hugeurlをアップデートした

twitterのURL展開隠しAPIを使っていたのだがいつの間にかなくなっていたので、HTTP-HEADしてresponseのlocationを見るようにした。

gem install hugeurl
gemの使い方はここに書いたのと同じ

 

今回は新たにhugeurlコマンドを付けておいた。gem installするだけで使えるようになっているはず。
% hugeurl http://t.co/abcde
で展開したり
% cat foo.txt | hugeurl
でファイルまるごと展開できる。

2

RubyでBuffalo/玄人志向の赤外線学習リモコンを操作する

11月22-23日にSFC ORFというSFCの研究室の発表会があって、そこでデモするブツに使う部品としてBuffaloの赤外線学習リモコンのRubyラッパーを書きました。これで家に帰る前に暖房つけたりできてうれしいですね。

玄人志向のKURO-RSとBuffaloのPC-OP-RSを操作できます。

MacとLinuxと、試してないけどたぶんWindowsでも動く気がする。コードはgithubに置いてる

学習リモコン/KURO-RS/(1)使ってみる – 脳みそ沸騰中!のPerlのコードを参考にしました。

■PC-OP-RSを買う
気がついたらKURO-RSがどこにも売ってないんだけど、PC-OP-RSがKURO-RSと同じハードウェアで箱と付属ソフトが違うだけなのでどちらでも動かせます。

BUFFALO PCastTV2対応 PC用学習リモコンキット PC-OP-RS1
バッファロー (2006-09-10)
売り上げランキング: 4538



■インストール
gem install kuro-rs


そしてKURO-RSをMacやLinuxに刺す。
Windowsの人はドライバを入れてBuffaloアプリが動くことを確かめてからUSBポートに刺す。
KURO-RSはUSBポートに接続するとシリアルデバイスとして認識されます。MacやLinuxなら/dev/tty.usb****という名前になる。WindowsならドライバをインストールしていればCOM1とかCOM2とか名前がつく。


■赤外線リモコンを学習する
kuro-rsというコマンドがgemと一緒にインストールされています。

terminalで実行する
% kuro-rs /dev/tty.usbserial-0012a3b4
そして15秒以内に赤外線をKURO-RSの本体に当てると、termialに16進数で赤外線データが出力されます。


学習した赤外線を発射しましょう
% kuro-rs /dev/tty.usbserial-0012a3b4 ffffffff0300f0e0018083...
のように第二引数に16進数でデータを与えます。

これでテレビのチャンネルが切り替わるはず。


■自分のプログラムから使う
こんな感じでIOっぽく使えます。くわしくはexamplesディレクトリを見るといい。
require 'rubygems'
require 'kuro-rs'

# open KURO-RS
kr = KuroRs.open('/dev/tty.usbserial-0012a3b4')

# read
puts kr.read
## => hex dump (ffffffff0300f0e0018083...)

# write
kr.write 'ffffffff0300f0e0018083'

# close
kr.close

# block
KuroRs.open('/dev/tty.usbserial-0012a3b4'){|k|
k.verbose = true
puts k.read
## => hex dump (ffffffff0300f0e0018083...)
}


■Webアプリから使う
シリアルポートは複数プロセスで共有できないし、また複数スレッドから同時に書き込んだりもできないのでRailsやSinatraアプリにkuro-rs gemをそのまま組み込むのはオススメできません。

そういう時はkuro-rs-serverを使いましょう。


こうすると8080番portでhttpサーバーが起動します
% kuro-rs-server /dev/tty.usbserial-0012a3b4 --port 8080


curlから赤外線読み書きしてみる
# read
% curl 'http://localhost:8080'
# => hex dump (ffffffff0300f0e0018083...)


# write
% curl -d 'ffffffff0300f0e0018083...' 'http://localhost:8080'
readもwriteも正常に行われるとstatus 200が返ります。失敗すると200以外。

kuro-rs-serverを内部APIとしてRailsやSinatraから、あるいはAjaxから使うのが良いと思います。