Raspberry Pi で node.js + WebSocket.io

logo
普通にaptで入れた node では WebSocket.io が動かないようなのでメモメモ

$ apt-cache search node | grep node

でnodeを探す。

nodejs - Node.js event-based server-side javascript engine
nodejs-legacy - Node.js event-based server-side javascript engine (legacy symlink)

それらしい nodejs と nodejs-legacy の2つが見つかるので新しい方を入れる

$ sudo apt-get install nodejs

npmでパッケージを入れる

$ npm install websocket.io

すると

npm WARN This failure might be due to the use of legacy binary "node"

どうもnodeが古くてwebsocket.ioが利用出来ないよう(nodejs v0.6.19)
これもlegacyかいっ

というわけで新しいnodeを入れる
Node.js v0.8.11 – Installation now easy
こちらに書いてあるように簡単そうなので v0.10.0 でも

$ wget http://nodejs.org/dist/v0.10.0/node-v0.10.0.tar.gz
$ tar xzvf node-v0.10.0.tar.gz
$ cd node-v0.10.0/
$ ./configure
$ make
$ make install

コンパイルに凄く時間がかかったのでバイナリを置いておきます
binary
node-v0.10.0-raspberrypi.tar

Raspberry Pi で mongodb

mongoDB
mongodbのコンパイルに凄く時間がかかったのでバイナリを置いておきます

コンパイル中にSDカード(4G)の容量が足りなくなるとかありました
ネットでmongodbの使い方を調べると、Raspberry Pi[ARMv6]用に用意された、
“mongo-nonx86” と “mongopi” の2つが見つかりますが mongopiの方が新しいです(MongoDB 2.1.1)
コンパイル方法
$ sudo apt-get install git-core build-essential scons libpcre++-dev xulrunner-dev libboost-dev libboost-program-options-dev libboost-thread-dev libboost-filesystem-dev
$ git clone git://github.com/RickP/mongopi.git
$ cd mongopi
$ scons
$ sudo scons --prefix=/opt/mongo install
デーモンの終了方法
mongod の起動方法は –dbpath オプションだけで起動しますが、
デーモンで起動している場合は kill -2 か kill -15 で終了させます
一番下辺り “Sending a UNIX INT or TERM Signal”

プロセスIDの探し方はこんな感じで紹介されてます

ps -ef | grep 'mongod' | grep -v grep | awk '{print $2}'
binary
mongopi2.1.1.tar.gz

※ /opt/mongo/bin/の中身ではなく strip結果です

Raspberry Pi が届いた

最近色々なところでよくネタになってるラズベリーパイを買ってみました。
このラズベリーパイはBeagleBoardの後発?な立ち位置?標準でPythonの開発環境やストアが入っています。
低スぺのPCにマイコン寄りなIOポートがついた感じです。いろいろ弄れそうでワクワク。
先月の11/15に注文して今日届きました。大体、一月ちょっと待ちです。
セットアップ+αまでメモメモ

2012-12-27 19.39.35

2012-12-27 22.29.55

2012-12-27 22.31.02

ARMマイコンのROMにSDから読み込んでブートするプログラムが予め書き込まれているので
SDカードに適切なイメージを書き込めば電源を入れるだけで簡単に起動します。

セットアップ
1. 家に転がっている適当なSDカードにOSのイメージを書き込む
2. ケーブルを接続して電源を入れる
以上です^^簡単すぎる

OSのイメージは http://www.raspberrypi.org/downloads でダウンロードできます。
Raspberry Piに最適化したというRaspbianかArch Linux が定番と思います。
今回はRaspbianで。2GのSDでギリギリ容量は足りました。
7から標準で入っているisoを焼くソフトではエラーが出ましたが、Win32DiskImagerで焼けました。 Linuxならddコマンド
※ Win32DiskImagerを起動したときになぜかエラーが出ましたが問題なく焼けました。

2012-12-27 21.22.002012-12-27 21.21.03

isoイメージの中身はFatとext4のパーティション構成に成っていて焼いたあと、windowsPCではFatのパテーションがそのまま開けます。linuxではどちらも開けます。
中にある config.txt をいじるとラズベリーパイの設定が変更できます。
オーバークロックなんかの設定もconfigにあります。

初回の起動時に raspi-config が開いて設定の編集ができますがあとから

$ sudo raspi-config

することでも設定し直すことができるのであまり設定に拘る必要はありません

中身はDebian Linuxの派生なので apt-get やら aptitude が利用できます。
リポジトリはラズベリーパイ用に置き換えられています。
SDカードが遅いせいかアップデートには結構時間がかかりました。

起動後はこちらのサイトで詳しく解説されています。
Raspberry Pi(ラズベリーパイ)の起動ガイド
http://lifescape.seesaa.net/article/283876741.html

config.txt詳細
RPiconfig
http://elinux.org/RPi_config.txt

ラズベリーパイのハードのwiki
RPi Hardware
http://elinux.org/RPi_Hardware

チューニングについて
R-Pi Troubleshooting
http://elinux.org/R-Pi_Troubleshooting#

IOポートの制御方法のwiki 各言語のサンプルが乗ってる
RPi Low-level peripherals
http://elinux.org/RPi_Low-level_peripherals#Introduction

IO制御について日本語で分かりやすく解説されてます
ラズベリーパイIO制御方法仕様調査結果
http://blogs.yahoo.co.jp/singleturbine/65834118.html

通信用の足があってAD変換が見当たらない辺り、センサは周りのハードに任せとく感じかな
通信で周りのマイコン達から情報を一箇所にまとめるとか面白そう

WebIOPi なるものを使えばブラウザからも簡単に制御できるそうです。

wxPythonメモ

wxPython。分かりやすくメモメモ
簡単にGUIがつくれて良い感じ。

テキストを2つ読み込んで組み合わせを表示するサンプルです

#! C:\Python27\python.exe
# -*- coding: shift-jis -*-

import wx       # wxPython
import xlwt     # Excel(書き込み)
import sys      # いろいろ

#-----------------------------------------------------------------------------
#    基本フレーム 基本パネル
#-----------------------------------------------------------------------------
class TestAppFrame(wx.Frame):

    Appname = ("TestApp")

    # コンストラクタ的なもの selfはコンテキスト
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, self.Appname, size=(900,400))

        # ファイルの読み込み in1.txt
        try:
            f = open("in1.txt", "r")
            load_str1 = f.read()

            f.close()
        except IOError:
            self.showMessage("in1.txtが見つかりません")
            sys.exit()

        # ファイルの読み込み in2.txt
        try:
            f = open("in2.txt", "r")
            load_str2 = f.read()

            f.close()
        except IOError:
            self.showMessage("in2.txtが見つかりません")
            sys.exit()

        # shift-jis を unicode型にデコード (後々文字コードでハマりやすいので内部ではUnicode型に統一する。らしい)
        load_str1.decode('shift-jis')
        load_str2.decode('shift-jis')

        # 要素一覧の生成
        load_list1 = load_str1.split("\n")
        load_list2 = load_str2.split("\n")

        # メインパネル生成 (1つ)
        main_panel = wx.Panel(self, wx.ID_ANY)

        # サブパネル生成 (2つ)
        sub_list_panel = list_panel(main_panel, load_list1, load_list2) # リストパネル
        sub_button_panel = button_panel(main_panel)                     # ボタンパネル

        # メインレイアウト (メインパネルの上にサブパネルを配置する)
        main_layout = wx.FlexGridSizer(1,2)
        main_layout.Add(sub_list_panel, flag=wx.GROW)
        main_layout.Add(sub_button_panel, flag=wx.GROW)
        main_layout.AddGrowableCol(0)
        main_layout.AddGrowableRow(0)

        # レイアウト確定
        main_panel.SetSizer(main_layout)

    def showMessage(self, word):
        dig = wx.MessageDialog(self, word, "エラー", wx.OK)
        dig.ShowModal()
        dig.Destroy()

#-----------------------------------------------------------------------------
#    リストパネル
#-----------------------------------------------------------------------------
class list_panel(wx.Panel):

    # publicな感じ
    data = []

    def __init__(self, main_panel, listdata1, listdata2):
        wx.Panel.__init__(self, main_panel, wx.ID_ANY)

        # self.XXXは privateな感じ
        self.stage1 = listdata1
        self.stage2 = listdata2
        self.stage3 = []

        # リストボックスの生成 (3つ)
        self.listbox1 = wx.ListBox(self, wx.ID_ANY, size=(200,-1), choices=self.stage1, style=wx.LB_HSCROLL|wx.LB_MULTIPLE)
        self.listbox2 = wx.ListBox(self, wx.ID_ANY, size=(200,-1), choices=self.stage2, style=wx.LB_HSCROLL|wx.LB_MULTIPLE)
        self.listbox3 = wx.ListBox(self, wx.ID_ANY, size=(300,-1), choices=self.stage3, style=wx.LB_HSCROLL|wx.LB_SINGLE)

        # リストボックスのイベントを登録
        self.listbox1.Bind(wx.EVT_LISTBOX, self.stage1_select)
        self.listbox2.Bind(wx.EVT_LISTBOX, self.stage2_select)

        # リストパネルレイアウト(リストパネルの上にリストウィジェットを配置する)
        layout = wx.FlexGridSizer(1,3)
        layout.Add(self.listbox1, flag=wx.GROW|wx.TOP|wx.LEFT|wx.BOTTOM, border=10)
        layout.Add(self.listbox2, flag=wx.GROW|wx.TOP|wx.LEFT|wx.BOTTOM, border=10)
        layout.Add(self.listbox3, flag=wx.GROW|wx.TOP|wx.LEFT|wx.BOTTOM, border=10)
        layout.AddGrowableCol(0)
        layout.AddGrowableCol(1)
        layout.AddGrowableCol(2)
        layout.AddGrowableRow(0)

        # レイアウト確定
        self.SetSizer(layout)

    def refresh(self):
        self.cache1 = list(self.listbox1.GetSelections())
        self.cache2 = list(self.listbox2.GetSelections())

        self.data = []
        for i in range(len(self.cache2)):
            for ii in range(len(self.cache1)):
                self.data.append( self.stage2[self.cache2[i]] + " x " + self.stage1[self.cache1[ii]] )

        self.listbox3.Set(self.data)

    def stage1_select(self, event):
        self.refresh()

    def stage2_select(self, event):
        self.refresh()

#-----------------------------------------------------------------------------
#    ボタンパネル
#-----------------------------------------------------------------------------
class button_panel(wx.Panel):
    def __init__(self, main_panel):
        wx.Panel.__init__(self, main_panel, wx.ID_ANY)

        # ボタンの生成 (2つ)
        button1 = wx.Button(self, wx.ID_ANY, "全てテキストで出力")
        button2 = wx.Button(self, wx.ID_ANY, "全てExcelで出力")

        # ボタンのイベントを登録
        button1.Bind(wx.EVT_BUTTON, self.click_button_1)
        button2.Bind(wx.EVT_BUTTON, self.click_button_2)

        # ボタンパネルレイアウト(ボタンパネルの上にボタンウィジェットを配置する)
        layout = wx.BoxSizer(wx.VERTICAL)
        layout.Add(button1, flag=wx.TOP|wx.LEFT|wx.RIGHT, border=10)
        layout.Add(button2, flag=wx.TOP|wx.LEFT|wx.RIGHT, border=10)

        # レイアウト確定
        self.SetSizer(layout)

    def click_button_1(self, event):
        f = open("out.txt", "w")
        for word in list_panel.data:    # こんな感じに他のクラスの変数にアクセス可能
            f.write(word.encode('shift-jis') + "\n")    # 何らかの文字コードにエンコードしてからwrite
        f.close()

        self.showMessage("out.txt を出力しました")

    def click_button_2(self, event):

        book = xlwt.Workbook()
        sheet = book.add_sheet("HAHAHA!!")
        sheet.write(1,1,"ALL list")

        for i, word in enumerate(list_panel.data):
            sheet.write(i + 2,1,word)                   # Unicode形式のままwrite

        book.save("out.xls")

        self.showMessage("out.xls を出力しました")

    def showMessage(self, word):
        dig = wx.MessageDialog(self, word, "out", wx.OK)
        dig.ShowModal()
        dig.Destroy()

#-----------------------------------------------------------------------------
#    main ここからはじまる
#-----------------------------------------------------------------------------
if __name__ == "__main__": # main() な感じ

    app = wx.App()
    frame = TestAppFrame()      # クラスが生成されコンストラクタ的に__init()__が呼び出される

    frame.Show()
    app.MainLoop()

<参考サイト>
python-izm
YAMAGUCHI::weblog – マルチバイト文字列のエンコード・デコード

nginxでwordpressのサイトを構築する

WindowsでNginxを構築します
最近はNginxが流行ってきているということで、Windowsでやってる方が少ないのもあって構築方法をメモメモ

Windows + Nginx + FastCGI + PHP + Mysql の組み合わせで WordPress が動作するところまでです
検証環境は Windows7x64 です

ダウンロード
必要なものを集めてきます。
Nginx → Stable Version nginx/Windows-1.0.12
PHP → PHP5.3 VC9 x86 Non Thread Safe
Mysql → MySQL Community Server 5.5.20 Windows (x86, 32-bit), MSI Installer
Wordpress → WordPress 3.3.1

解凍
NginxをC:\Program Files\nginx-1.0.12 に解凍
PHPを C:\Program Files\php-5.3.10-nts-Win32-VC9-x86 に解凍
Wordpressを C:\www に解凍
Mysqlをインストール。(ry

動作確認
1. まずNginxの動作確認。
“C:\Program Files\nginx-1.0.12\nginx.exe” を起動してから、ブラウザで localhost に接続する。
「 Welcome to nginx! 」と表示されればOK

2. 次にPHPの動作確認
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 の項目のコメントアウトを外して次のようにする

location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}

“C:\Program Files\php-5.3.10-nts-Win32-VC9-x86\php-cgi.exe -b 127.0.0.1:9000” で PHPを起動し、
“C:\Program Files\nginx-1.0.12\nginx.exe -s reload” で変更した設定を読み込む。
ブラウザで localhost/tekitou.php にアクセスします。
「 No input file specified. 」と表示されれば、Nginx PHP 間のやり取りは成功です

WordPressを動かす

“C:\Program Files\nginx-1.0.12\conf\nginx.conf” の

location / {
root html;
index index.html index.htm;
}

を以下のようにする

location / {
root C:/WWW;
index index.php index.html index.htm;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 の項目を

location ~ \.php$ {
root C:/;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME C:/WWW$fastcgi_script_name;
include fastcgi_params;
}

にする。

“C:\Program Files\php-5.3.10-nts-Win32-VC9-x86\php.ini-production” を コピーして php.ini を作成する
そして php.ini の
;extension=php_mysql.dll のコメントアウトを解除して
extension=php_mysql.dllにする

phpを再起動する。

ブラウザで localhost に接続する

完了。

自動起動するようにする
ポートを介してphpを利用するためIISやApacheと違って事前にphpを起動させておく必要があります。

batファイルを作って起動時に実行させます

start C:\"Program Files"\php-5.3.10-nts-Win32-VC9-x86\php-cgi.exe -b 127.0.0.1:9000
start C:\"Program Files"\nginx-1.0.12\nginx.exe

参考サイト
nginx + PHP on Windows in 5 minutes
Install WordPress on WEMP (Windows, nginx, MySQL and PHP)
nginxの起動オプション
CGI版のPHPで「No input file specified.」のエラーを解決する方法
fastcgi_param SCRIPT_FILENAME パラメータの意味
WordPressを100倍速くする! MySQLの調整やnginx proxy cache
ソースファイルが shift-jis だと文字化けする問題 「未解決」