職場の人の結婚パーティでやったあれこれ

Standard

結婚パーティという大炎上案件が先ほど無事に終わったので、やったことを書きます。
デジタルなことをがっつりお手伝いしました。@ononoさん、@k13styleさん、ボク(@bugcloud)でやってみたいことをいろいろ詰め込んでみたので、これからなんかやる人の参考になればと。
 

やったこと

  • パーティの受付で、お客さん1人1人の動画を撮影してアニメーションGIFに。WEBサイトにアップして、会場内のプロジェクターでスクリーンに投影。
  • ↑のGIFを使ってくじ引き。当選者発表ムービーにGIFを合成。
  • アキラくん(新郎)人形にプロジェクションマッピング。しゃべる人形こわい。
  • 式で撮った写真をウェルカムムービーに。
  • おめでとうムービー。サプライズでアイさん(新婦)のおばあちゃんからのメッセージつき。
  • アキラTシャツ
  • アキラ風船 200個

 
ボクは上2つをやりました。
 

パーティ受付時に、お客さん1人1人の動画を撮影してアニメーションGIFに。

これはもくもく開発会@鎌倉で作ったiPhoneアプリです。このパーティ専用のiPhoneアプリを作りました。撮影した動画をアニメーションGIFに変換してサーバーにアップロードてくれるいい子です。
↓な感じのアニメーションGIF。
gif
100+人の写真を撮れるのか心配だったんですけど、3人で意外にもまわりました。
 

WEBサイトにアップして、会場内のプロジェクターでスクリーンに投影。

↑のアプリで作ったアニメーションGIFを受け付けるサーバープログラムと、それを表示するWEBページを作りました。よく結婚パーティでポラロイドで写真を撮ってボードに貼ってたりするんですけど、あれの写真が動く版です。
http://uploader.あきら.com/gif_images
会場のみんなの見える化wみたいなのけっこうおもしろかったです。前日の夜に@ononoさんと@k13styleさんの意見でアニメーションを再生 → 逆再生のループになるようにアプリを改修したんですが、正解だったなと。いい感じに楽しそう感でました。
 

GIFを使ってくじ引き。当選者発表ムービーにGIFを合成

アップロードされたアニメーションGIFをランダムに抽出するプログラムを書いてくじ引き。事前に@ononoさんが撮影した動画に当選した人のGIFを合成しました。ペラ1の当選結果ページを作って、JavaScriptで動画に合成しています。
↓な感じ
http://bugcloud.com/develop/akira/01/
 
ブラウザのキャッシュで会場にいない人に当たるっていうハプニングがありましたw
 
 

反省とまた機会があれば改善すること

  • とにかく当日の準備時間ない。会場に1時間前に到着するも店に入れてもらえず30分前に会場入り。20分後にはお客さんが入ってくるというドタバタ感。司会の人にだいぶ助けてもらいました。
  • 事前の打ち合わせ足りてない。大人ってそう簡単にみんな集まれない!
  • 会場でシュミレーションしときたい。
  • もっとデザインにこだわりたい。時間さえあれば。
  • 当日のオペレーションでいろいろなんとかなる。基本的にみんな祝に来てるので優しい。
  • 新婦の名前.新郎の名前.com みたいな日本語ドメインはかなりオススメ(nginxで日本語ドメインを設定する方法は → http://qiita.com/bugcloud/items/680c2ced3a268953da6c)

 

感想

身近な人のために書くコードは気持ちがいいよ!
 
 
さいごに
アキラさんアイさん、ご結婚おめでとうございます。
末永くお幸せに。

Raspberry Piでマイコン超入門

Standard

@k13styleさんとRaspberry Pi超入門ハッカコンをしてきたので備忘録。
 

セットアップ

 
OSはRaspbianをインストールした。↓がよくまとまってる。
Raspberry Pi初心者のためのOS別セットアップガイド
 
RaspbianにはデフォルトでGUIのWifi設定ツールがインストールされているのでこれを使って無線LANにつないだ。使い方は↓にまとまっている。
Raspberry Piで遊ぼう [No.6:無線LANを接続しよう]
 
いろんなケーブルを抜き差しして非常にじゃまなので、極力すっきりしておいた方がいいと思う。Raspbianはインストール時にSSHサーバーの設定もできるので、Wifiの設定が終わったらHDMIケーブルとマウス・キーボードも抜いてOK。電源ケーブルのみの最スマート構成がおすすめ。
 
とりあえずいつも使ってる環境とRubyをインストールしておく。RVMで1.9.3はインストールできたけど、ビルドに1時間ぐらいかかって泣いた。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install vim zsh git
sudo apt-get install build-essential
sudo apt-get install curl
sudo apt-get install zlib1g-dev
sudo apt-get install libreadline6-dev
sudo apt-get install libssl-dev 
sudo apt-get install libyaml-dev
curl -L https://get.rvm.io | bash -s stable
rvm install 1.9.3
rvm use 1.9.3 --default
sudo ln -s /home/pi/.rvm/rubies/default/bin/ruby /usr/local/bin/ruby
sudo ln -s /home/pi/.rvm/rubies/default/bin/irb /usr/local/bin/irb

 
ちなみにRuby 2.0.0はインストール中にコケてめんどくさくてやめたけどたぶん必要なライブラリを全部入れれば普通に入るはず。
 
 
 

LEDチカチカ

 
マイコンと言えばまずはこれが登竜門らしい。最初はGPIOすら使わずピンから電源を供給してみる。ここにGPIO用のチートシートがあったのでこれを見ながら作業した。LEDを3.3Vのピンとグラウンドに繋ぐと
 
20130506-001

20130506-001

 
ペカッ
“GOGO”って透かしを入れたくなる。
 
 
次にGPIOからLEDを制御してみる。
富豪マイコンらしくRubyを使ってみる。Pi Piperっていうかっこいい名前のライブラリがあるのでそれを使う。
https://github.com/jwhitehorn/pi_piper
サンプルがたくさんあっていい感じ。こんな感じになった。

上のチートシートの11番、GPIO 17番ピンを使う。モールス信号のサンプルとか試して人生初GPIO制御を堪能した。
https://github.com/jwhitehorn/pi_piper/wiki/Project-1:-Morse-Code
 
あとこういう

LEDテープを光らせたりしたんだけど、オームの法則も忘れてるような文系クソ野郎だったせいで、いい歳したオッサンがテープ光らせるのに2時間ぐらいかかった。トランジスタとか使うの難しすぎて笑ったw工業高校1年生ぐらいの回路が組めるようになったので
http://www.adafruit.com/products/420
これでクラブでモテるiPhoneカバーを作ろうと思う。

IRCサーバーとロイディ

Standard

人工無能について知る必要があって環境を作ったのでメモ。

  • unit hostingという国産のIaaSを利用。
    OSはCent OS 5.9 (unit hostingは今のところこれしか選べない)
  • IRCサーバーはyumでインストールできるircd-hybridを選択

 

ロイディとは

東京工業大学 ロボット技術研究会の市川 宙 (Gimite) さんが中心となって作成した日本語人工無脳。Rubyで書かれている。
http://rogiken.org/SSB/reudy.html
 
本家のロイディ(Reudy Ver.3.09)がRuby 1.9に対応していないので、今回は1.9でも動くように改変されたReudy1.9をRuby 2.0で動かした。
人工無能 Reudy (ロイディ) 1.9
https://github.com/Glasssaga/Reudy19
 
 
 

IRCサーバーの準備

IRCサーバー用にunit hosting上にサーバーを用意する。unit hostringのサーバー構築オプションにはユーザスクリプトなるものがあって、シェルスクリプトのURIを指定しておくと、構築完了後にrootユーザーでそのスクリプトを実行してくれる。Gist使うのが楽。
https://gist.github.com/bugcloud/5363980
 
↑でRVMとかrbenvでRubyのインストールとかできる状態になるはず。RPMforgeとEPELリポジトリも追加される。ircd-hybirdはEPELにあるのでyumでインストールする。デフォルトだと設定項目おおすぎて涙目になるのでシンプルなやつをコピーしてきて必要な部分だけ編集。

yum --enablerepo=epel install ircd-hybrid
cp /etc/ircd/ircd.conf /etc/ircd/ircd.conf.orig
cp -irp /usr/share/doc/ircd-hybrid-7.2.3/simple.conf /etc/ircd/ircd.conf

 
/etc/ircd/ircd.conf

serverinfo {
        name = "irc.example.com";
        sid = "000";
        description = "IRC Server";
        hub = no;
};

別にいらないけど一応パスワードを設定。

# YOUR_SALTは適当に変更
/usr/libexec/ircd/mkpasswd -m -s YOUR_SALT

“plaintext:”って表示されるのでパスワードを入力するとハッシュ化されたパスワードが表示される
/etc/ircd/ircd.confを編集

auth {
        user = "*@*";
        class = "users";
        password = "↑で表示されたパスワード";
        encrypted = yes;
};

 
起動と自動起動設定

service ircd start
chkconfig ircd on

 
終わり。これでIRCクライアントから接続可能なはず。SSLとか使ってないので変なこと言うのはやめましょう。
 
 
 

ロイディ

RVMでRubyをインストールする。その名の通りRuby 1.9向けに作られたReudy1.9はRuby 2.0でも動いた。Ruby 1.9でも動かしたけど、2.0のときだけ、ときどき発言してこなくなることがある気がした。
 

# Install RVM and Ruby 2.0
curl -#L https://get.rvm.io | bash -s stable --autolibs=3 --ruby

適当なディレクトリに https://github.com/Glasssaga/Reudy19 をcloneしたら設定ファイル(public/setting.yml)にIRCサーバーの情報とかを書く。:encoding:を”UTF-8“にしたら動かなかった。いつもの

incompatible character encodings: ASCII-8BIT and UTF-8

的なの出てオチる。
 
lib/reudy/bot_irc_client.rbに1行追加すると動く。

 48           #受信ループ。
 49           while line = sock.gets
 50             line = line.force_encoding(@user.settings[:encoding] || "ISO-2022-JP")
 51             on_recv(line)

 

# publicは設定ファイルやDB,ログのディレクトリ
ruby irc_reudy.rb public

でロイディ起動。publicディレクトリをコピーしてsetting.ymlのニックネームだけ変えれば複数のロイディを投入できる。
 
2013-04-12

20130412

 
一見ただのオウム返しに見えるけど、何気に会話として成立する率高い。

Taskerとnmaで”Find My iPhone”が作れるよ。そう、Androidならね

Standard

iPhone5の発表を目前にして、Androidのメモです。
 
iPhoneをなくしてしまった時に端末の現在地を確認できたりする“Find My iPhone”ですが、当然Android端末でも同じようなことしたいわけです。Google Playで検索すれば同じことができるアプリがたくさん出てきます。が、そこは自分でやるのが楽しいAndroidなのでTaskerを使って実現してみます。
 
 
Android端末についてのアレコレを自動化してくれるという、すべてのAndroidユーザがインストールすべきTaskerですが、今回やろうとしていることと同じことをやっているサンプルはネット上で見つけることができます。ただK-9っていうメーラーアプリを使っていることが前提になっているので、ボクは設定していませんでした。
 
http://www43.atwiki.jp/taskeru/pages/15.html

■K-9で指定メールアドレスから受信をした際に、携帯電話所在地を特定電話番号へSMS送信。■
[Context]Evnet>>3rdParty>>K9 EmailReceived (from 指定メールアドレス)
[Task]
Misc>>GPS>>on
Misc>>GetLocation(source GPS)
Misc>>GPS>>off
Net>>SendSMS(number[送信先携帯電話番号] ,Message[%LOC])
※LOC は取得した現在地を表す変数です。

出来れば、紛失した携帯の所在地を確認するために、送信したメールアドレスに現在地を返信したいのですが、方法が分かりません。

 
で、ある時Taskerの[Evnet] >> [3rd Party]の中に「Notify My Android」っていうのがあるのを見つけまして、調べてみると「Notify My Android (nma)」っていうのはAndroid端末に外部から通知を送ることができるサービスでした。
https://www.notifymyandroid.com/
https://play.google.com/store/apps/details?id=com.usk.app.notifymyandroid&hl=ja
見落としていたことが残念でしかたありません。自動化ライフにかなり役立ちそうなサービスであります。このアプリをインストールして、アカウントを作成後、サイトにログインすると、ここから端末にマニュアルで通知を送ることができるようになります。
 
Screenshot_from_2012-09-05_001

20120906

 
この通知をトリガーとして現在地をどこかに送信するタスクをTaskerに設定してみます。
 
Context
===============================================================
[Evnet] >> [3rd Party] >> [Notify My Android]
>> (App“Web Notification”と入力)
 
20120906-001

20120906-001

===============================================================
 
 
Task
===============================================================
5つです。
20120906-002

20120906-002

 

  1. [Misc] >> [GPS]
    >> (SetOn)
  2. [Misc] >> [Get Location]
    >> (SourceAny)
  3. [Misc] >> [GPS]
    >> (SetOff)
  4. [App] >> [Calendar Insert]
    >> (Calendarは虫めがねボタンを押していつも使ってるGoogleアカウントを選択、
    Titleは適当な文字列、
    Description%DATE, %TIMEを含んだ文字列
    Location%LOCと入力)
    20120906-003

    20120906-003
  5. [Net] >> [HTTP Post]
    >> (設定値は後述)

===============================================================
 
Taskについて簡単に解説します。
1.〜3.で現在地を取得しています。端末をなくした場合を想定しているので、バッテリーを節約するために、現在地を取得したらGPSをオフにしています。
2.の設定値で、SourceAnyにしていますが、こうすると、GPSではじめに取得して、取得できなかったら、基地局から取得するらしいです。
4.で取得した現在地をGoogleカレンダーに記録しています。Android端末のアカウント同期機能を使っていれば、記録された情報を別の端末やPCから確認することができます。上の設定値だと
Screenshot_from_2012-09-05_003

20120906-004

という感じで登録されます。
5.Googleカレンダーだけでもいいですが、アカウントの同期機能を使っていないこともあるので、位置情報をメールで自分に送ってみます。Taskerからは「特定のメールアドレスにメールを送る」っていうのはできないっぽい(SMSは送信できる)ので、どっかのサーバにプログラムを置いて、そこにTaskerからリクエストを送信、そのプログラムでリクエストをメールに変換して送信っていう感じでやりました。
設定値は
20120906-130822

20120906-005

な感じです。見たままです。メールを送信するプログラムは
 
post-2-mail.php

<?php
/*
 * Send E-mail from POST request
 * POSTリクエストをE-mailに変換して送信するスクリプト
 *
 *  Request Parameters
 *    now: DateTime
 *         日時
 *    loc: Location - Latitude and Longitude
 *         場所 - 緯度・経度
 */

require_once("Common.php");

$mail_to = YOUR_EMAIL_ADDRESS;
$mail_from = "Your.Android.Phone";
$mail_title = "I'm here!";
$mail_body = <<<EOD
This E-mail has been sent from your phone.
  Time: CURRENT_DATE_TIME
  Loc:  CURRENT_LOCATION
EOD;

if ( isset($_POST) && !empty($_POST) ) {
  if ( isset($_POST['now']) && !empty($_POST['now']) ) {
    $now = str_replace("_", " ", $_POST['now']);
    $now = str_replace(".", ":", $now);
    $mail_body = str_replace("CURRENT_DATE_TIME", $now, $mail_body);
  }
  if ( isset($_POST['loc']) && !empty($_POST['loc']) ) {
    $mail_body = str_replace("CURRENT_LOCATION", $_POST['loc'], $mail_body);
  }
  Common::send_jp_mail(
    array(
      'to' => $mail_to,
      'subject' => $mail_title,
      'body' => $mail_body,
      'from_email' => $mail_from,
      'from_name' => $mail_from
    )
  );
}

 
Common.php

<?php
class Common {
  /*
   * This method send a mail for Japanese.
   * (charaset of the email is 'ISO-2022-JP')
   *
   *  Parameters
   *    to:           sending email's TO
   *    cc:           sending email's CC
   *    bcc:          sending email's BCC
   *    subject:      sending email's subject
   *    body:         sending email's body
   *    from_email:   sending email's From and Reply-To
   *    from_name:    sending email's From and Reply-To
   *    attach_files: sending email's attach files.
   *                  This parameter is Array type, so you can set multiple files.
   *
   *  Return
   *    The result of sending as TRUE or FALSE.
   */
  public static function send_jp_mail( $params = array() ) {
    $to = ( array_key_exists('to', $params) ? $params['to'] : null);
    $cc = ( array_key_exists('cc', $params) ? $params['cc'] : null);
    $bcc = ( array_key_exists('bcc', $params) ? $params['bcc'] : null);
    $subject = ( array_key_exists('subject', $params) ? $params['subject'] : null);
    $body = ( array_key_exists('body', $params) ? $params['body'] : null);
    $from_email = ( array_key_exists('from_email', $params) ? $params['from_email'] : null);
    $from_name = ( array_key_exists('from_name', $params) ? $params['from_name'] : null);
    $attach_files = ( array_key_exists('attach_files', $params) ? $params['attach_files'] : array());
    $boundary = null;
    $has_attachment = is_array($attach_files) && count($attach_files) > 0;
    if ($has_attachment) {
      $boundary = md5(uniqid(rand(), true));
    }

    $headers  = "MIME-Version: 1.0 \n" ;
    $headers .= "From: " .
                "".mb_encode_mimeheader (mb_convert_encoding($from_name,"ISO-2022-JP","AUTO")) ."" .
                "<".$from_email."> \n";
    $headers .= "Reply-To: " .
                "".mb_encode_mimeheader (mb_convert_encoding($from_name,"ISO-2022-JP","AUTO")) ."" .
                "<".$from_email."> \n";
    $headers .= "Cc: ".$cc."\n";
    $headers .= "Bcc: ".$bcc."\n";
    if ($has_attachment) {
      $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
    } else {
      $headers .= "Content-Type: text/plain;charset=ISO-2022-JP \n";
    }
    $headers .= "Content-Transfer-Encoding: 7bit";


    /* Convert body to same encoding as stated
    in Content-Type header above */

    if ($has_attachment) {
      $r_body = $body;
      $body = "--$boundary\n";
      $body .= "Content-Type: text/plain; charset=\"iso-2022-jp\"\n";
      $body .= "Content-Transfer-Encoding: 7bit\n";
      $body .= "\n";
      $body .= mb_convert_encoding($r_body, "ISO-2022-JP","AUTO")."\n";

      foreach ($attach_files as $file) {
        if (!file_exists($file)) {
          continue;
        }
        $filename = basename($file);
        $body .= "\n";
        $body .= "--$boundary\n";
        $body .= "Content-Type: application/octet-stream; name=\"$filename\"\n";
        $body .= "Content-Disposition: attachment; filename=\"$filename\"\n";
        $body .= "Content-Transfer-Encoding: base64\n";
        $body .= "\n";
        $body .= chunk_split(base64_encode(file_get_contents($file)))."\n";
      }
      $body .= '--'.$boundary.'--';
    } else {
      $body = mb_convert_encoding($body, "ISO-2022-JP","AUTO");
    }

    /* Mail, optional paramiters. */
    $sendmail_params  = "-f$from_email";

    mb_language("ja");
    $subject = mb_convert_encoding($subject, "ISO-2022-JP","AUTO");
    $subject = mb_encode_mimeheader($subject);

    $result = mail($to, $subject, $body, $headers, $sendmail_params);
    return $result;
  }
}

 
という感じです。これもそのままです。メールがたくさん来たら困る人はリクエストパラメータに固定のキーでも埋め込んだらいいと思います。
 
 
タスクの設定が終わったら保存して、上述のnmaのサイトから自分の端末に通知を送ってみます。
Screenshot_from_2012-09-05_002

20120906-006

っていう感じのメールを受信できました。
 
 
参考(Taskerでデフォルトで使える変数)
http://tasker.dinglisch.net/tour.html#variables
http://www43.atwiki.jp/taskeru/pages/17.html