いくつか試して、とりあえずシリアル通信について、なんとか動かすことができたので手順を記録しておく。
NW.jsはNode.js + Chromiumなアプリ開発プラットフォーム。JavaScriptで書くところがミソだが世の中はElectronのほうが多いような気がしている。それはともかく。
通信に限らないとはいえ、C++によるネイテイブコードを含むNode.jsのモジュールはWindowsではやっかいだ。UNIXとWindowsで挙動の違う関数、Windows側にバグがある関数などがあって動かない、というのが多く見受けられるパターン。
また、ビルドにはnode-gypを使うようだが、 この環境作りにPython2.7とVisual Studio 2015が必要という、そこそこのハードルがある。VSもまともにインストールするとおおごとだし、node-gyp開発者側にPython3対応にする気が全くないようなので(GitHubのIssueのつれない感じからの類推)、node-gypだけの小さな閉鎖環境が望ましいことになる。というわけで、そんなパッケージが用意されたようだ。以下のコマンドを「管理者権限つきの」コマンドプロンプトに
npm install --global --production windows-build-tools
ただし、すでにVS2015が入っていると、node-gypは一通り動くものの、NW.js対応にするときにやっかいなことになった(普段VSをC++の開発環境に使っているなら問題はないんだろうと思う)。詳しくはhttps://github.com/nodejs/node-gyp#installationのWindowsの注意書きを参照していただきたいが、「Common Tools fot C++」としてまとめられたツールやライブラリ群をVS2015を起動し、C++のプロジェクトを作る作業をすることでインストール開始させなければならない。
準備ができたところで、いきなりNW.js対応を作る前に、通常のNode.js用インストールをして動作テストをするのがよいと思う。これはnpmを使うなら、プロジェクトのディレクトリを作り、そのなかでnpm initしてpackage.jsonを作成したあと、、
npm install serialport
動作確認ができたあとは、NW.js用にリビルドが必要となる。Node.js用のままNW.jsで読み込もうとしても、はDLLエラーのようなことが生じて動かない。
NW.js用には、nw-gypという、node-gypのフォークモジュールがあって、それを入れておく必要があるらしい。また、node-pre-gypモジュールも入っていたほうが無難なようだ。
nw-gypの実行には、binding.gyp(C++のオブジェクトをJavaScriptのオブジェクトに結びつける設定ファイル)のある場所でなければならないようだ。そこで、node_modulesの下の、serialportの下にcdする。(cd node_modues\serialport)
このあたりになってくると、UNIXの操作に近くなってくるので、Gitをインストールし、その際に、コマンドプロンプトでMingWin由来のUNIX互換コマンドが動くよう設定しておくと気持ちが楽になると思う。GIt Bash上でやってもよいのかもしれないけれど、試してはいない。
リビルドのコマンドを実行する前に、NW.jsのバージョン(Node.jsやChromiumのバージョンではない)を確認しておく必要がある。NW.EXEを実行すれば、右下のいちばん上に、「nw.js v0.30.5」などのような表示が見えるので、それを控えておく。あるいは、ZIPを展開したフォルダ名が配布されたままならば、フォルダ名にバージョン番号が入っているので、それをみてもよい。
この先は、相性によって2つの方法を試してコンパイルが通るほうを選ぶようだ。また、python.exeが環境変数PATHに通っていなければいけないようなので(node-gypは%HOME%\.npmrcファイルの設定を読んでPython2.7の実行パスを決めてくれるが、nw-gypやnode-pre-gypは見ないようだ。Windowsでは、コマンドプロンプトに「set PATH=%PATH%;Python2.7のパス」のように、セミコロンで連結するのが流儀。%ではさんだ変数名は、変数参照を意味するので、既存のPATHに、Python2.7のパスを追加したことになる。
これでようやく実行。
nw-gyp rebuild --runtime=node-webkit --target=バージョン番号
または
node-pre-gyp rebuild --runtime=node-webkit --target=バージョン番号
のようだ。当方では今回は、nw-gypでコンパイルが通った。詳しくは、Qiitaの@sashimizakanaさんのエントリ「node-webkitでネイティブモジュールを使う」を参照。バージョン番号を指定してリビルドしていることから、NW.jsのバージョンが変わるたびにリビルドが必要になるんだろうと思う。
動作チェックに使った、シリアルポートの一覧表示スクリプトを含むHTMLファイルを掲載しておく。ポートオブジェクトをJSONで、見えた数だけ列挙するというもの。console.log()も入れているのでデバッガのコンソールにも出る。元ネタはこちら。NW.js用ではないけれど、シンプルかつ丁寧に説明されていて、わかりやすいと思う。DOM操作は、VSCodeエディタの予測候補を見ながら適当に書いた。index.htmlのファイル名として、npm initしてpackage.jsonを作るときのmainに、デフォルトのindex.jsではなくindex.htmlと入力してある。
<!DOCTYPE html>
<head>
<title>Hello World!</title>
<script>
var SerialPort = require('serialport');
// list serial ports:
SerialPort.list(function (err, ports) {
ports.forEach(function(port) {
portString = JSON.stringify(port);
console.log(portString);
title = document.getElementById('h1');
p = document.createElement('p');
text = document.createTextNode(portString);
document.body.appendChild(p).appendChild(text);
});
});
</script>
</head>
<body>
<h1 id="title">Hello World!</h1>
<p id="port"></p>
</body>
</html>
NW.jsからは、プロジェクトのディレクトリ名を引数に与えるのが簡単だと思う。
以上、ご参考まで。
以上、ご参考まで。