4時間半睡眠

流行りものに弱い。前は1時に寝て7時くらいに起きる6時間睡眠(90分×4?)をほぼ実践していたけど、ここ1週間は3時に寝て7時くらいに起きるというのを続けている。昼間特に眠くなることはないし、熟睡は出来ているので結構良いのかも。でも増えた時間をチェスと将棋に使っていたら意味ないな・・・ちゃんと溜まっている仕事とか調べものに使わないと。もう少し朝が明るくなったら、あるいは11時30分に寝て4時起きにして運動をしても良いかな。

問題は、デスクワークだけをしている時は4.5時間でも十分なのかもしれないけど、家の周りの肉体労働を始めると絶対に無理なんじゃないかな?

Lilypondで楽譜作成(OS X Leopard)

古典調の篠笛とか太鼓を習っていて、練習のために何回か楽譜に起こしたことがある。今まではフリーのFinale Notepadを使っていたのだがいまいち使い勝手が良くないので、オープンソースのLilypondを使ってみた。OS X Leopardではうまく動かない、などの情報も見かけたけど、ここのガイドにある「一番簡単な手法」と半日の練習でうまく使えるようになりました!慣れればマウスでちまちまおたまじゃくしを並べるよりずっと早いし、仕上がりもFinale Notepadよりかなり良い(ちゃんと調整すれば「出版にも耐えうる」出力ができるそうだ)。Smultronというテキストエディタもシンプルでなかなか素敵だ。

その後TeXShopでのやり方も試してみた。こちらも悪くはない。

欠点としてはコンパイルにちょっと(といっても30秒くらい?)時間がかかるとういところかな。でももうFinaleには戻れませんなー。

バーコードリーダーを使った図書管理[書きかけ]

補習校の図書館の貸し出しシステムをバーコードと「MonJack」というフリーソフトで構築してみた。
ソフト自体はそれほど複雑ではないけど、本の読み込みが面倒。
私本管理Plus」というのもあるのだけど、扱いにくいのでAmazonAPIExcelを組み合わせてISBNから本の情報をゲットするファイルを作ってみた。
ASINがあるセルを選択して(ただしいっぺんにクエリできるのは10件まで)


Sub LookupMultipleBookInfoR(r As Range)
On Error Resume Next

Dim url As String
Dim oReq, oDOM As Object
Dim oDOM As Object
Dim oNodeList As IXMLDOMNodeList
Dim c As Range
Dim count, i As Integer
Dim i As Integer

Set oReq = CreateObject("MSXML2.XMLHTTP")
Set oDOM = CreateObject("MSXML2.DOMDocument.3.0")

oDOM.async = "false"
AWSAccessKey = "1Q70HSY9N7XXXXXXXX" 'ここは自分のアクセスキーを使ってね
url = "http://webservices.amazon.co.jp/onca/xml?" & _
"Service=AWSECommerceService&AWSAccessKeyId" & AWSAccessKey & _
"&Operation=ItemLookup&ResponseGroup=Medium&ItemId="

For Each c In r.Cells
url = strURL & c.Text & ","
count = count + 1
Next

url = Left(strURL, Len(strURL) - 1)
oReq.Open "GET", strURL, False
oReq.send

oDOM.loadXML (oReq.responseText)
Set oReq = Nothing

Set oNodeList = oDOM.getElementsByTagName("Item")
For i = 0 To oNodeList.Length - 1
Set oItem = oNodeList.Item(i)
Asin = oItem.getElementsByTagName("ASIN")(0).Text
Set oAttributes = oItem.getElementsByTagName("ItemAttributes")(0)
PictureURL = oItem.getElementsByTagName("LargeImage")(0).getElementsByTagName("URL")(0).Text
BookTitle = oAttributes.getElementsByTagName("Title")(0).Text
'For Each ba In oAttributes.getElementsByTagName("Author")
' BookAuthor = BookAuthor & "," & ba.Text
'Next
BookAuthor = oAttributes.getElementsByTagName("Author")(0).Text
Publisher = oAttributes.getElementsByTagName("Manufacturer")(0).Text
PublicationDate = oAttributes.getElementsByTagName("PublicationDate")(0).Text
FormattedPrice = oAttributes.getElementsByTagName("FormattedPrice")(0).Text
Binding = oAttributes.getElementsByTagName("Binding")(0).Text
NumberOfPages = oAttributes.getElementsByTagName("NumberOfPages")(0).Text
Height = oAttributes.getElementsByTagName("PackageDimensions")(0).getElementsByTagName("Length")(0).Text
EAN = oAttributes.getElementsByTagName("EAN")(0).Text

If Len(PublicationDate) = 7 Then
yr$ = Left(PublicationDate, 4)
mt$ = Right(PublicationDate, 2)
PublicationDate = yr$ & "/" & mt$ & "/01"
End If

For Each c In r.Cells
If c.Text = Asin Then
c.Offset(0, 1).Value = BookTitle
c.Offset(0, 2).Value = BookAuthor
c.Offset(0, 3).Value = Publisher
c.Offset(0, 4).Value = PublicationDate
c.Offset(0, 6).Value = FormattedPrice
c.Offset(0, 8).Value = Binding
c.Offset(0, 9).Value = NumberOfPages
c.Offset(0, 10).Value = Height
c.Offset(0, 13).Value = PictureURL
If (c.Offset(0, -1).Value = "") Then
c.Offset(0, -1).Value = EAN
End If
End If
Next
Next
End Sub

coLinuxなど

MacBook黒を買ったので、会社のWindowsノートにいろいろごちゃごちゃ入れなくて済む様になった。でもUNIX環境は必要だし、MacBookをいつも会社に持っていくのも面倒なので、もう一度Windows上のUNIX環境の見直し。前回暇だったときにcoLinuxでいろいろ遊んでいたけど、その後VMWareが無料化されて放棄してしまった。しかし、VMWareはやはり遅いし、coLinuxの0.7.1 RCなるものが最近出ているようなので、最初からやり直してみた。会社のネットワーク環境で使うという前提で以下の通り。

  • 最新のcoLinuxインストーラを拾ってきてインストール
  • インストール時にDebianのイメージを拾ってくるオプションがあるけどプロキシを通さなければならないので、後でマニュアルダウンロード
  • 以前はWinpcapのブリッジモードを使ったけど、coLinuxを会社のネットワークに直接つなぐと怒られる可能性があるので、TAPドライバとNATを使うことにする
  • 設定の方法はhttp://eto.com/d/coLinuxInstall.htmlをほとんどそのまま。以前は設定がXMLファイルだったのがCONFファイルになっています。
  • 上記の手順と違うのは、あとSWAPファイルを設定しているくらいかな?インターネット接続の設定がグループポリシーで非表示になっていたのでregeditを使って解除する。
  • 起動時のコンソールをntにするために、起動にはcolinux-daemon.exe -t nt @debian.confとする。
  • 起動後、aptをプロキシを通して使うために/etc/apt/apt.confを設定:

Acquire
{
http {
proxy "http://username:password@X.X.X.X:8080/";
}
ftp {
proxy "ftp://username:password@X.X.X.X:8080/";
}
Retries "0";
};
APT::Cache-Limit 12582912;

  • Cache-Limiはあとでstableからtestingにアップグレードするときに"Dynamic MMap ran out of room"とか苦情を言われるのでその対策
  • /etc/apt/sources.listを編集してstableをtestingに変更
  • apt-get update、apt-get dist-upgrade
  • アップグレードは途中で面倒なことが起きる・・・(http://nixcraft.com/how-to-solve-apt-get-upgrade-problem-vt190.html
  • apt-get installでお好きなものを適当にインストールして行く
  • passwdでrootのパスワードの設定。adduser akibareでユーザを追加。
  • /etc/sshd_confでpassword認証、challenge/response認証を禁止。
  • visudoでsudo出来る人を限定
  • /etc/securettyでrootログオンをconsoleとtty1に限定
  • iptablesで基本的な設定(必要ないけどbest practiceの練習として)
  • akibareユーザのRSA public/privateキーペアを生成(http://www.jitaku-server.net/ssh_crypto.html
  • キーをcofs0で設定したWindowsフォルダにコピー。Puttyの設定。
  • root以外のパスワードを削除。sudowersでakibare ALL、NOPASSWDの設定。
  • Puttyでログオン・sudo出来ることを確認。

(続き)Bluetooth近接検知装置

前回書いたシェルスクリプトは、BlueZに付属しているhcitoolを使ったけどひとつ問題がありました。デバイスが検知範囲外の場合に、探す時間が長すぎるという問題。スクリーンセーバーの応用では特に問題ないけど、ラップタイマーの場合は、10秒とか考え込んでしまうと困るので、2,3秒で見つからなければ検索を止めてほしかった。

そこで、最初はPerlで書き直して、fork()した上でhcitoolを使い、親プロセスで3秒経ったらhcitoolが走っている子プロセスをTERMするというのを試してみたのだけど、なぜか知らないけど10回くらいTERMしたらデバイスがおかしくなってしまったみたいで、検知範囲にあるのに検知できなかったりした。がっかり。

どうにか待ち時間を指定できないのかと調べていたら、Inline::Cを使った例に、BlueZのライブラリを直接使う方法が書いてあったので、やってみたよ。つまりlibbluetoothでexportされているhci_read_remote_nameという関数で、待ち時間を指定できる。その間CPANのProxy設定、LD_LIBRARY_PATHの環境変数の設定などいろいろ障害物はあったけど。。。まあ満足がいくように動きます。以下がhcitool nameに相当するモノ。例では2秒に設定してあります。


#! /usr/bin/perl

use Inline C => Config =>
MYEXTLIB => '/usr/local/lib/libbluetooth.so';
use Inline C => <
#include
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include

#include
#include
#include

SV * devname( char * address )
{
bdaddr_t bdaddr;
char name [248];
int dd;

str2ba( address, &bdaddr );
int dev_id;
dev_id = hci_get_route(&bdaddr);
if ( dev_id < 0 )
{
/* printf("Device not available"); */
return ( newSVpvf("") );
}

dd = hci_open_dev(dev_id);
if ( dd < 0 )
{
/* printf("HCI device open failed"); */
return ( newSVpvf("") );
}

if ( hci_read_remote_name( dd, &bdaddr, sizeof(name), name, 2000 ) != 0 )
{
close(dd);
return ( newSVpvf("") );
}

close(dd);
return ( newSVpvf( "%s", name ) );
}

EOT

#-------------------------------------------------------------------

use strict;
use warnings;

printf(devname("00:0b:0d:40:f1:4f") . "\n");

関係ないけど、Perlの編集はEclipseのプラグインでして、sambaでシェアしたvmwareのドライブに直接保存していたら、改行コードがおかしいことに気が付いて(Windows XPでEclipseを動かしているのでLFじゃなくてCRLFになっている)調べた結果、Exclipseの開発で長いこと検討されているのに標準のグローバルスイッチが無いらしいことを発見(Javaの環境変数に依存するみたい)。でもとりあえずメニューから[File - Convert Line Delimiter - UNIX]で解決しました。

Bluetooth近接検知装置

http://q.hatena.ne.jp/1156781413
初めて注目の質問に載っちゃった!べつに嬉しくないけど!

Bluetoothを近接検地装置(proximity monitor)として使うのはそんなに目新しいことではなくて、たとえばここではGentoo Linuxで、PCから離れたら自動的にスクリーンセーバーが起動するという方法が説明されています。Bluetoothドングル、Bluetooth対応デバイス(何でも良い。イヤホンとかマウスでも!)とLinuxとちょっとしたシェルスクリプトで出来てしまいます。

Linuxにはだいたい標準でBluezというBTスタックがインストールされており、付属のツールであるhciconfig、hcitoolなどでBTをコントロールできる。ちなみにドングルはClass 1と2があって、Class 1は100メートルほど、Class 2は10メートル程度の範囲。スクリーンセーバー起動装置としてはClass 2が良いし、上司検知器としてはClass 1が良いだろう。

質問の通り、Windows XPでネイティブに実行するのは簡単じゃなさそうなんだけど、世の中も便利になり、無料のVMWareを使えば大丈夫です。USBは2つまで接続できて、試してみたけどストレージだけじゃなくてBluetoothドングルも使えました。

ドングルを接続して、Windowsが認識した後にVMWareで[VM - Removable Devices - USB - ]とメニューで選ぶと表示されるので、選びます。その後VMWareのUSBブリッジ(?)がWindowsに認識され、正式にホストOSから利用可能になる。そこでhciconfig(引数なし)を実行すると

#hciconfig
hci0: Type: USB
BD Address: 00:11:XX:YY:ZZ:AA ACL MTU: 678:8 SCO MTU: 48:10
UP RUNNING PSCAN ISCAN
RX bytes:117 acl:0 sco:0 events:15 errors:0
TX bytes:313 acl:0 commands:15 errors:0

みたいな結果が出てくるはずです。状態が"DOWN"の場合は、

#hciconfig hci0 up

としてあげれば走り出します。次にターゲットとなるデバイスのBDアドレス(MACアドレスと同じようなもの)を取得しなければなりませんが、これはデバイスの発見モードをONにして後で、hcitool scanでスキャンを開始します。

#hcitool scan
Scanning ...
00:22:XX:YY:ZZ:AA Palm OSハンドヘルド

上記の例ではSonyClieを発見モードにしてみました。このBDアドレスをメモしておきます。上司検知システムの場合はもうちょっと難しいですが、「部長の携帯ってBT対応なんですか?かっこいい、ちょっとやって見せてください」とかおだてて発見モードをONにしてもらうとか、またはメーカーからある程度予測できるので、btscannerといようなツールを使ってブルートフォース(総当り)で発見することも可能です。

最後に発見する方法ですが、hcitool name というコマンドを使えば、ペアリングしなくても装置が近くにいるか分かります。用は「あなたの名前は?」というコマンドで、BDAddressを知っていればパスワードはいりません。ここでデバイスの名前が返ってくれば「いる」、タイムアウトすれば「いない」という判定になります(質問で書いたRSSIというシグナルの強度は、残念ながらあらかじめConnectしていないと使えないみたいなんです)。

#hcitool name 00:22:XX:YY:ZZ:AA
Palm OS ハンドヘルド

最後のステップとしては、上記のコマンドを繰り返し実行して、返り値によって他のコマンドを実行するシェルスクリプトを書けばいいわけです。こんな感じ:

while [ 1 ]
do
RESULT=`hcitool name $1`
if [ "$RESULT" != "" ]; then
## (上司検知機の場合):近くにいるぞ、ゲームを隠せ!
## スクリーンセーバの場合:近くにいるからなにもしなくて良い
else
## (上司検知器の場合):居ないみたいだ、ゲームをしよう!
## スクリーンセーバの場合:スクリーンセーバー起動
fi
done

ちなみに、上のほうで紹介したGentooの例では、hcitool cc で接続した上でhcitool rssi で信号強度を測るという方法を使っています。これでも良いのですけど、ヘッドセットの場合はうまくconnectできなかったりしたので、hcitool nameが一番確実なのかな?あとはl2pingというのもあります。

参考までに、hcitoolとかのツール郡ではなくて直接ライブラリを使ったサンプルPerlとInline:Cを使っている)へのリンクもこちらに。

「わずか3KB」って嘘

Gigazineの記事【ファイルサイズわずか3KBのオーバーレイ効果「Litebox」登場】
わずか3KBなのはmoo.fxのことで、Litebox自体は合計22KBくらいだよん。
でも使ってみた。簡単で美しい。

http://www.jsa.asn.au/events/soccer2006/