« ニコニコ動画勉強会に行ってきました | メイン | FizzBuzz - Golf Challenge »

Multi-USB::MissileLauncher for Win32

YAPC::Asia 2007 Tokyo で大人気だった USB::MissileLauncher をマルチに制御するパッチを作りましたので公開します。

Multi-USB::MissileLauncher for Win32 binary package
http://namazu.org/~takesako/pub/usblauncher-20070501.zip

Triple USB Missile Launcher

■ ctlmissileコマンド使用法

Usage: ctlmissile [ up | down | left | right | fire | stop ] [ 3000]

オリジナルからの変更点

http://www.earth.li/~noodles/files/usblauncher-0.0.3.tar.gz からの変更点

* ctlmissile.c.patch

  1. コンパイルオプション -DLINUX -DWIN32 の追加
    (Linux以外のWindows、Mac OS X の環境でも動作するように)
  2. msec秒でコマンドを発行するコマンドライン引数 [ 3000 ] を追加
  3. 複数のUSBミサイルランチャーの接続に対応
    同時制御と逐次制御が可能

■ インストール方法

Windows の場合

事前にLibUsb-Win32からダウンロードできるlibusb-win32-filter-bin-0.1.12.1.exeをインストール

$ gcc -DWIN32 ctlmissile.c -o ctlmissile -lusb

Linux の場合

ディストリビューション付属のlibusbパッケージをインストール

$ gcc -DLINUX ctlmissile.c -o ctlmissile -lusb

Mac OS X の場合

libusbをインストール

$ gcc ctlmissile.c -o ctlmissile -lusb

■ 応用

POE::Component::Server::TCPを使って、USBミサイルランチャーを制御するTCPデーモンを1時間で書く。

missile_server.pl

#!/usr/bin/perl
use POE qw(Component::Server::TCP);
use strict;

sub main {
  my $bind_port = $ARGV[0] || 6969;

  my $kernel = POE::Component::Server::TCP->new(
    Port     => $bind_port,
    Error    => \&error_handler,
    Concurrency => -1,

    ClientInput        => \&handle_client_input,
    ClientConnected    => \&handle_client_connect,
    ClientDisconnected => \&handle_client_disconnect,
    ClientError        => \&handle_client_error,
    ClientFlushed      => \&handle_client_flush,
    ClientShutdownOnError => 0,
  );

  POE::Kernel->run();
}

sub accept_handler {
  my ($socket, $remote_address, $remote_port) = @_[ARG0, ARG1, ARG2];
}

sub error_handler {
  my ($syscall_name, $error_number, $error_string) = @_[ARG0, ARG1, ARG2];
}

sub exe {
  my ($cmd) = @_;
  $cmd =~ s/[^\s\d\w]//g;
  system split(/\s+/, $cmd);
}

sub handle_client_input {
  my $heap = $_[HEAP];
  my $kernel = $_[KERNEL];
  my $input_record = $_[ARG0];
  my $msg = "yes sir, $input_record";
  if ($input_record =~ m/(shutdown|quit)/i) {
    $kernel->yield("shutdown");
    $msg = "connection closed...";
  } elsif ($input_record =~ m/help/i) {
    $msg = "Ugage: [ up | down | left | right | fire | stop ] [ 3000 ]";
  } elsif ($input_record =~ m/^\s*$/ims) {
    $msg = "help";
  } else {
    exe("ctlmissile $input_record");
  }
  $heap->{client}->put($msg);
}

sub handle_client_error {
  my ($syscall_name, $error_number, $error_string) = @_[ARG0, ARG1, ARG2];
}

sub handle_client_connect {
  my $heap = $_[HEAP];
  $heap->{client}->put("connected on USB-Missile-Launcher 200 OK");
}

sub handle_client_disconnect {}

sub handle_client_flush {}

main();

1;

POEのプログラミングは初めてでしたが、perldoc POE::Component::Server::TCP 見ながら簡単に書けました。

■参考URL

YappoLogs: ミサイルは国境を越える 
http://blog.yappo.jp/yappo/archives/000504.html

Google Maps: ミサイルが本当に国境を越えてる???
http://maps.google.com/maps?q=38.22657,-112.299&z=18&t=k

Tilting Google Maps and MissileLauncher - SlideShare (miyagawa-san at osdc.tw)
http://www.slideshare.net/miyagawa/tilting-google-maps-and-missilelauncher/

throw new CybozuLabsException() - libusbを使うPHP Extensionを作りました
http://labs.cybozu.co.jp/blog/tsuruoka/anubis/blog_show/43

TokuLog 改め Perl を極めて結婚するブログ - missile on ruby. 
http://d.hatena.ne.jp/tokuhirom/20070407/1175935832

西尾泰和のブログ @ Cybozu Labs: PythonワンライナーでUSBミサイルランチャーを制御 
http://labs.cybozu.co.jp/blog/nishio/2007/04/pythonusb.html

*BSDでのUSBデバイスドライバーの実装
http://www.ofug.net/~yamajun/presentation/2003/usb.html

ToDo

ctlmissile.cで複数のミサイルランチャーを制御する拡張コマンドを追加したので (ひ)メモ - Assurer::Plugin::Notify::Missileの概要設計の実装が待たれるところです。