工作と競馬

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

カテゴリ:4.ソフトウェア > 4.7 javascript

概要

ラズパイZeroWから、Google Homeを喋らせることができた。


背景と目的

以前、WindowsPCからGoogle Homeを喋らせた。今回は、手持ちのRaspberry Pi Zero Wを使ってしゃべらせることにした。


詳細

1.Node.jsとnpmのインストール

まず、nodejsとnpmのインストールは、こちらにしたがい、

sudo apt-get update
sudo apt-get install -y nodejs npm
sudo npm install npm n -g
sudo n stable

という感じ。以下で、バージョンの確認。バージョンはそれぞれ、v9.4.0と5.6.0となった。

node -v
npm -v


2.google-home-notifierのインストール

次に、こちらにしたがい、以下コマンドを実行。

sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
git clone https: //github.com/noelportugal/google-home-notifier
cd google-home-notifier
npm install

ここでインストール完了と思い、4のコードを実行したが、エラーが発生。こちらを参考に、以下を追加で実行。

sudo npm install --unsafe-perm mdns
sudo npm install --unsafe-perm homebridge


3.コーディング

以前と同じ以下のコードを作成。

var googlehome = require('google-home-notifier');
var language = 'ja';
 
// IPアドレスの設定
googlehome.device('Google Home', language).accent(language).ip('xxx.xxx.xxx.xxx');
 
// しゃべらせる
googlehome.notify('こんにちは', function(res) {
  console.log(res);
});


4.実行

上記をnodeで実行したところ、

ディロン!...こんにちは。

としゃべった。というわけで、しゃべりが相変わらずノロいが成功だ。

ただし、以下のような警告メッセージが出る。どうやったら、直せるのか現状ではわからない。このあたりをやれば解決するんだろうか。。。

*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>


まとめ

ラズパイZeroWから、Google Homeを喋らせることができた。Windowsの時もそうだったが、どうもインストールがすんなり行かない。いろいろ、試しながら上記の手順に落ち着いたが、今後もOSのバージョンが変わったりすると、うまくいかなくなりそうな気がする。

概要

 Cognito User Poolsを使って、ログインページを作ってみたところ、うまく動作させられた。そのときの手順をメモった。


背景と目的

 私は、今までにAWSのAPI GatewayやLambdaを使ってサーバーレスのWebサイトを構築したことがあるが、ユーザー認証が必要なページは作成したことがないので、サーバーレスでユーザー認証まで可能なサイトが構築できないかと思い、Web上を調べたところ、Cognitoというサービスを使うと、できるという情報がたくさん出てきた。そこで、このCognitoを使ってログインページまで作って、作り方を一通り習得する。


詳細

1.全体の流れ

 今回やることの全体の流れを書き出すと、以下のような感じ。

  • Cognitoで、User Poolを作る
  • Cognitoで、Identity Poolを作る
  • javascriptで、サインアップページを試しに作ってみる
  • javascriptで、ログインページを試しに作る
2.参考サイト

 Web上を探したところ、以下などがあった。というより、参考1がそのものなので、それをなぞった。

  • 参考1=http://qiita.com/horike37/items/1d522f66452d3abe1203
  • 参考2=http://qiita.com/teradonburi/items/ef535d19c28a009552ec
  • 参考3=http://dev.classmethod.jp/cloud/aws/cognito-user-pool/
3.Cognito
3.1 User Poolを作る

 User Poolは、参考2で説明されているとおり、ユーザー認証をするたの仕組みだそうだ。ユーザープールというくらいだから、どんなユーザーがいるかという情報を溜めておくところということか。

 早速、参考サイト3の手順に従い、Cognitoで、Manage your user poolsボタン>Create a User Poolボタンと進む。今回は、名前をtestpoolとして、あとはデフォルトでどんどん進んだ。出来上がったものが、図3.1。ここまでで、ユーザが溜められる箱ができた感じだ。

userpool

 図3.1 作成したUser Pool

3.2 User Poolを作る

 Identity Poolは、参考2で説明されているとおり、ロール認証をするたの仕組みだそうだ。誰が何ができて、何ができないというのがロールだから、その情報を溜めておくところということか。

 参考サイト1の手順に従い、Cognitoで、Manage Federated Identitiesボタン>Create new identity poolボタンと進む。名前をTestIdentityPoolとして、こちらもデフォルトでどんどん進んだ。ただし、1か所だけ注意事項として参考1で挙げられているUnauthenticated identitiesも有効化をチェックを入れた。出来上がったものが、図3.2。Authentication Provider>Cognito>User Poolで、3.1で作ったUser Pool IDを入力したので、これでユーザを溜める箱とその箱の中のユーザが何ができて何ができないかという情報が結びつけられた感じかな。

identitypool

 図3.2 作成したIdentity Pool

4.javasriptで実装
4.0 javascriptで実装するための準備

 次に、javascriptで先ほど作ったものにアクセスして、ユーザ認証できるか試す。

 まず、javascriptで実装するのに必要となるものは、以下の6つ。それぞれリンク先で入手できる。

4.1 javascriptで、サインアップページを試しに作ってみる

 コードは、参考1にそのものが載っているので、ほぼそのまま。図4.1は、サインアップボタンを押してサインアップがうまくいった様子。ユーザが追加されている。

    // 設定
    var REGION = '...'; // リージョン
    var IDENTITY_POOL_ID = '...'; // Identity PoolのID
    var USER_POOL_ID = '...'; // User PoolのID
    var APP_CLIENT_ID = '...'; // User Poolで作ったAppのID

    // リージョンとクレデンシャルの設定
    // AWSとAWSCognitoの両方を設定する
    AWS.config.region = REGION;
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: IDENTITY_POOL_ID
    });
    AWSCognito.config.region = REGION;
    AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: IDENTITY_POOL_ID
    });

    // UserPool
    var poolData = {
      UserPoolId: USER_POOL_ID,
      ClientId: APP_CLIENT_ID
    };
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);

    // サインアップする関数
    function signUpButton() {

      var attributeList = [];

      var dataEmail = {
        Name: 'email',
        Value: $('#email').val()
      };

      // AttributeEmail
      var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail);

      attributeList.push(attributeEmail);

      // サインアップを実行
      userPool.signUp($('#email').val(), $('#password').val(), attributeList, null, userPool_signUp_callback);

      // サインアップ完了時のコールバック
      function userPool_signUp_callback(err, result) {

        if (err) {
          console.log(err);
          return;
        }

        cognitoUser = result.user;
        console.log('user name is ' + cognitoUser.getUsername());
        console.log('call result: ' + result);

      }
    }

    // サインアップボタンに関数を割り当て
    $("#signup").on("click", signUpButton);
signup
図4.1 サインアップできた様子

4.2 javascriptで、ログインページを試しに作る

 こちらも、参考1ほぼそのままで試しに書いただけという感じ。図4.2は、ログインボタンを押してログイン成功時のWebブラウザのデバッグコンソール画面の様子。AccessTokenが表示された。

    // 設定
    var REGION = '...'; // リージョン
    var IDENTITY_POOL_ID = '...'; // Identity PoolのID
    var USER_POOL_ID = '...'; // User PoolのID
    var APP_CLIENT_ID = '...'; // User Poolで作ったAppのID

    // リージョンとクレデンシャルの設定
    AWS.config.region = REGION;
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: IDENTITY_POOL_ID
    });
    AWSCognito.config.region = REGION;
    AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: IDENTITY_POOL_ID
    });

    // UserPool
    var poolData = {
      UserPoolId: USER_POOL_ID,
      ClientId: APP_CLIENT_ID
    };
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);

    // ログインボタン用の関数
    function logInButton() {

      // AuthenticationDetails
      var authenticationData = {
        Username: $('#email').val(),
        Password: $('#password').val()
      };
      var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);

      // cognitoUser
      var userData = {
        Username: $('#email').val(),
        Pool: userPool
      };
      var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);

      // サインアップを実行
      cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: login_success,
        onFailure: login_failure
      });

    }

    // ログイン完了時のコールバック
    function login_success(result) {
      console.log('access token + ' + result.getAccessToken().getJwtToken());
    }

    // ログイン完了時のコールバック
    function login_failure(err) {
      console.log(err);
    }

    // ログインボタンに関数を割り当て
    $("#login").on("click", logInButton);
login
図4.2 ログインを試した結果


まとめと今後の課題

 Cognito User Poolsを使って、ログインページを作ることができた。これで、サーバーレスでユーザ認証のあるWebサイトが作れそうだ。

概要

 jquery、API Gateway、Lambdaで、jsonデータをやり取りする方法をメモっておく。


背景と目的

 jquery、API Gateway、Lambdaで、jsonデータをやり取りするのに、いちいち毎回調べるのが面倒なので、メモっておく。


詳細

1.やること

 まず、やることを整理すると以下。

  • Webサイトのjavascriptなどから、jqueryのajaxを使ってjsonデータ付きで、API Gatewayにアクセスする
  • API Gatewayは、渡されたjsonデータをLambda関数に渡す
  • Lambdaは、受け取ったjsonデータに基づき処理し、jsonのデータを返す
  • API Gatewayは、LambdaのレスポンスをWebサイト側に返す
2.Webサイト側実装

 注意点は以下。

  • jsonデータは文字列化(シリアライズ)する。
  • 受け取るデータdataTypeを指定する。
  • 送信データcontentTypeを指定する。
$.ajax({
    type: "POST",
    url: "送信先URL",
    data: JSON.stringify({ param1: value1, param2: value2, … }),
    dataType: "json",
    contentType: "application/json",
    success: function(resp){...},
    error: function(err){ … }
});
3.APIGatewayの実装
3.1 メソッドの作成

 メソッドは、LambdaプロキシのPOSTメソッドを作成。

3.2 メソッドリクエスト、統合レスポンス、メソッドレスポンス

 何も設定しなくてよい。

3.3 統合リクエスト

 ここが重要。本文マッピングテンプレートで、application/jsonのテンプレートを追加し、

 {
割当先キー名 : $input.json("$.参照先キー名”)
}

 というようなテンプレートを作成。送信されたjsonデータがマッピングできる。データ全体が欲しければ、$input.json("$”)でよい。なお、以下あたりを参考にして、さらに任意のマッピングをするとよい。

4.Lambda関数

 lambda_handerの引数eventに、先ほどのマッピングテンプレートでマッピングした結果が格納される。なので、event["キー名”]とすれば、マッピングしたキー名のデータが参照できる。
戻り値は、jsonエンコード可能なオブジェクトで返せばよい。3.2で設定しない場合は、Webサイトまでそのまま引き渡される。


まとめと今後の課題

 まとめておいたので、次回以降迷わないはず。

概要

 TI社製センサータグCC2650用のjavascript APIであるnode-sensortagを使い、無事動作することを確認した。


背景と目的

 以前、TI社製センサータグCC2650とRaspberry PiをBLE通信させたが、その際は、bluezを使って動作させていた。しかし、最近久しぶりにいじろうとして少しWeb上で調べ物をしていたら、javascript(Node.js)で動かせるということがわかった。そこで、そのAPIを使って動かせるか試す。


詳細

1.ダウンロードとインストール

 私の環境は、Nodeがv5.4.0で、こちらを参考にインストール。

npm install -g sensortag

 しかし、エラー発生。私の環境の場合、libudev-devというのが足らないとメッセージが出たので、こちらを参考に、以下を実行。

apt-get install libudev-dev

 再度、sensortagインストールしたところ無事完了。

2.実装

 とりえあえず、デバイスの検出と接続、加速度の取得くらいまでできるといいと思うので、やってみた。こちらを参考に、実装したプログラムは以下。

// センサタグ
var sensorTag;

// モジュールの読み込み
var SensorTag = require('sensortag').CC2650;

// 接続解除時
function disconnectCallback(){
 console.log('disconnected!');
 process.exit(0);
}

// 接続成功時
function connectAndSetUpCallback() {
 console.log("connectAndSetUp!");
 
 // 加速度センサを有効化
 sensorTag.enableAccelerometer(function(){
  // 有効化成功したら、通知ON
  sensorTag.notifyAccelerometer(function(){
   // 通知ON成功したら、何もしない
  });
 });
 
}

// 加速度変化通知を受け取ったら
function accelerometerChangeCallback(x, y, z){
 console.log('\tx = %d G, \ty = %d G, \tz = %d G', x.toFixed(3), y.toFixed(3), z.toFixed(3));
 console.log('\ty = %d G', y.toFixed(3));
 console.log('\tz = %d G', z.toFixed(3));
}

// デバイス発見したとき
function onDiscover(st) {

 console.log("discovered!");

 sensorTag = st;
 
 // 接続解除処理の割り当て
 sensorTag.on('disconnect', disconnectCallback);
 
 // 加速度変化時処理の割り当て
 sensorTag.on('accelerometerChange', accelerometerChangeCallback);
 
 // 接続する
 sensorTag.connectAndSetUp(connectAndSetUpCallback);

}

// メインの処理
console.log("start!");
SensorTag.discover(onDiscover);
3.動作確認

 動作させた様子が以下。

sudo hciconfig hci0 up
node test_sensortag.js

 とBTドングルを起動させるのを忘れない。CC2650の電源ボタンを投入すると、早速デバイスが発見され、接続が完了。その後1秒ごとに加速度がどんどん送られてきた。無事成功。

テスト
図3 実行した様子

参考メモ

まとめと今後の課題

 node-sensortagをインストールし、動作できることを確認した。これで、bluezを使うより、扱いがだいぶ楽になる木がする。

概要

 ラズパイにて、Web上の音楽ソースを鳴らしてみた。


背景と目的

 諸事情により、ラズパイを使ってNode.jsでWeb上に置いた音楽ファイル(wav、mp3等)を鳴らすプログラムを作る必要が出た。そこで、方法の調査と実装をしてみる。


詳細

1.調査

 Webブラウザでは、Web Audio APIとXMLHttpRequestを使うことで、Web上の音楽ソースをダウンロードし、再生することができる。なので、Node.jsでも同じようにすればよいと思った。そこで、Node.jsでこれらを使うにはと、調べたところ、それぞれ以下に情報があった。

 それぞれ、Node.js向けのパッケージとして作成されたもののようだ。これをインストールして使おうと思う。

2.実装
2.1 環境

 今回使用する環境は以下。

  • デバイス=Raspberry Pi 2 Model B
  • OS=Raspbian Jessie
  • Node.js=v5.4.0
2.2 node-web-audio-apiをインストール

 方法は、リンク先の通りだが、一応書くと、

npm install -g web-audio-api

 なお、私の環境だけかもしれないが、インストールエラーが出た。エラーメッセージによれば、alsa/asoundlib.hがないという。こちらを参考に、

sudo apt-get install libasound2-dev

 をしてから、再度インストールしたところうまくいった。

2.3 node-xmlhttprequestをインストール

 方法は、リンク先の通り。

npm install -g w3c-xmlhttprequest

 こちらはとりあえずすんなり。

2.4 コーディング

 参考リンク先のExample : playing back sound with aplayに倣い、標準出力にデコードしたオーディオデータを出力し、aplayで読み取るという流れにする。

// web-audio-apiの読み込み
var AudioContext = require("web-audio-api").AudioContext;

// w3c-xmlhttprequestの読み込み
var XMLHttpRequest = require('w3c-xmlhttprequest').XMLHttpRequest;

// AudioContextの取得
var context = new AudioContext();

// BufferSourceの作成
var source = context.createBufferSource();

// 出力先の設定(標準出力)
context.outStream = process.stdout;

// 接続
source.connect(context.destination);

// ターゲットの音源のURL
var url = "ターゲットのURL"

// 音源をロードする関数
function loadSound(url) {
 var req = new XMLHttpRequest();
 req.open('GET', url, true);
 req.responseType = 'arraybuffer';
 req.onload = function () {
  var onSuccess = function (buffer) {
   source.buffer = buffer;
   source.start(0); // 再生開始
  }
  var onError = function (err) {
   console.log("error!"); // エラーの時
  }
  context.decodeAudioData(req.response, onSuccess, onError);
 }
 req.send();
}

// 音源のロード
loadSound(url);
3.動作確認

 以下のコマンドを実行。

node myScript.js | aplay -f cd

 結果、無事、再生された。
ただし、wavファイル以外(mp3,m4aなど)はうまく再生できなかった。何か追加でコーディングが必要なのかもしれない。ちょっと現時点では試してないのでわからない。というわけで、wavファイルは成功!


まとめと今後の課題

 限定的だが、ラズパイ上で、Node.jsを使ってWeb上の音楽ソースを鳴らすコーディングができた。

概要

 Web標準のNotificationという機能を使って、Webブラウザから通知を出せるか試してみた。


背景と目的

 Webサイト内で、ユーザーに通知をする方法を試す必要が出たので、試した結果をメモる。


詳細

1.調査

 まず、Webブラウザでの通知機能について調べたところ、こちらにあるように、ブラウザ上の機能として、
Notification
Web Push
という2種類の方法があるようだ。
 このうち、今回はサーバとのやりとりは要らないので、Web標準のNotificationという機能について、試すことにする。なお、参考になったサイトは以下。

  • http://qiita.com/yoshi6jp@github/items/8b24b93b7f7442001d65
  • https://developer.mozilla.org/ja/docs/Web/API/notification
  • http://kuwalab.hatenablog.jp/entry/2013/10/21/184254
2.実装
2.1 環境

 今回使用する環境は以下。

  • デバイス=ノートPC Lenovo IdeaPad Yoga 14
  • OS=Windows10
  • Webブラウザ=Chrome 52.0.2743.116
2.2 コーディング

 動作としては、ページを開くと、10秒に1回通知を行うというもの。コードは以下。HTML部は、省略。
ページロード時に、ユーザーに通知の許可を訪ねる。
notifyMe関数をsetInterval関数で、10秒ごとに呼び出すようにした。
Notificationの第2引数に、オプションとしてタグ、通知本文、通知アイコン画像が渡せる。アイコン画像は、手持ちの適当なうさぎのぬいぐるみ画像を使用。

// ロード時
if (!("Notification" in window)) {
 // 通知機能をサポートしていなければアラートを表示
 alert("This browser does not support desktop notification");
} else if (Notification.permission !== 'denied') {
 // 許可をまだ得ていなければ許可を得る
 Notification.requestPermission();
}

// 通知を作成する関数
function notifyMe() {

 if (Notification.permission === "granted") {
  // 通知を作成
  var options = {
   tag: "タグ",
   body: "通知の本文",
   icon: "icon.png"
  }
  var notification = new Notification("通知のタイトル", options);
  // クリック時のイベント
  notification.addEventListener('click', function () {
   // 何か処理
  });
  // 一定時間経過後に消す
  setTimeout(function () {
   notification.close();
  }, 3000);
 }

}
// 10秒ごとに通知を発生
setInterval(notifyMe, 10000);
3.動作確認

 図3の通り、表示された。オプションで渡したtagというものがどこに反映されているのかわからなかった。
なお、私はBracketsというエディタで作業していたが、ライブプレビュー機能(ブラウザに表示されるURLがfile://…になる)では動かなかった。しかたないので、ローカル上にWebサーバを立ち上げて、サイトにアクセスしたところちゃんと動いた。
また、このページがフォアグラウンドでない場合や、ブラウザ自体が最小化されていても通知はちゃんとされる。なので、ブラウザでとりあえずページを開いて置けばこの機能は生きる。(スマホはだめだと思う。手持ちのiPhone(SafariおよびChrome)では、そもそもNotificationが使えないという表示が出た。)

通知
図3 通知が表示された様子


まとめと今後の課題

 Web標準の機能であるNotificationの使い方がわかった。

静的なウェブサイトを作っているときに、動的サイトのCGIパラメータようにページへの入力パラメータが持たせられないかと思って考えたが、URLのページ内リンクを利用するといいのではないかと思った。

アクセスされた自身のURLは、javascriptでlocation.hrefというコマンドで取得できる。通常の使用方法では、cccで指定されたidと一致する要素の位置を表示するが、window.onload関数内などで、

http://aaa.bbb.html#ccc

とアクセスされたとき、

window.onload = function(){
    myURL = location.href;
    var x = myURL.split("#");
    // x[1]に基づき、各種処理...
}

といった感じでページ内リンクの文字列を取得すれば、ページ内リンクに応じて処理を切り替えできる。つまり、実質的に入力パラメータの役割ができる。

概要

 Node.jsを使ってWebブラウザからGPIOを操作するプログラムを作成し、動作を確認した。


背景と目的

 前回、WebブラウザからGPIOを操作するために必要なプログラム要素を調べ、テストできた。今回は、それらの要素を組み合わせて、実際にWebブラウザからGPIOを操作してみる。


詳細

1.コーディング

 前回のソースコードを参考に、以下のようなソースコードを作成した。Webページには、ONボタンとOFFボタンがあり、それらを押すとLEDが点灯/消灯するという仕組み。これを動作確認するため、Webブラウザでページを表示し、ONボタンを押したところLEDが点灯した。OFFで消灯した。これで目標を達成!ようやくたどり着いた。これから先も、ラズパイをjavascriptで操作していろいろ遊べそうだ。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>WebからGPIOを操作</title>
    </head>
    <body>
        <h1>WebからGPIOを操作</h1>
        <form>
        <button type="submit" name="SW" value="ON" formaction="" formmethod="POST">ON</button>
        <button type="submit" name="SW" value="OFF" formaction="" formmethod="POST">OFF</button>
        </form>
    </body>
</html>
var qs = require('querystring');
var fs = require('fs');
var http = require('http');
var exec = require('child_process').exec;

exec('gpio -g mode 7 out');

function serveron(request, response) {

        if (request.url == '/favicon.ico'){
                return;
        }

        console.log(request.method);

        if (request.method == 'POST'){
                var body = '';
                request.on('data', requeston);
                function requeston(data){
                        body += data;
                }
                request.on('end', requestonend);
                function requestonend(){
                        var query = qs.parse(body);
                        if (query["SW"] == 'ON'){
                                exec('gpio -g write 7 1');
                        } else {
                                exec('gpio -g write 7 0');
                        }
                }
        }

        fs.readFile('test.html', 'utf-8', readFileCallback);

        function readFileCallback(err, data){
                response.writeHead(200, {'Content-Type': 'text/html'});
                response.write(data);
                response.end('');
        }
}

var server = http.createServer();

server.on('request', serveron);

server.listen(8124);

まとめと今後の課題

 Raspberry Pi で、Node.jsを使ってWebブラウザからGPIOを操作することができた。今後も、javascriptでいろいろラズパイをいじってみたい。

概要

 Node.jsを使って、WebブラウザからRaspberry Pi のGPIOを操作するため、必要な情報収集を行った。


背景と目的

 前回、Node.jsを使ってWebサーバーが立ち上げられた。今回はWebブラウザからGPIOを操作するために必要なプログラム要素を情報収集し、動作テストしてみる。


詳細

1.情報収集、流れの確認、環境

 実現するまでのステップとして、

  • javascriptでGPIOを操作する方法を知る
  • Node.jsでHTMLファイルを表示する方法を知る
  • Node.jsで、クエリを取得する方法を知る
  • 上記3つを組み合わせてWebブラウザからGPIOを操作できるようにする

 というのが必要と分かった。今回は、上3つをそれぞれ順に進めてみる。私の環境は、Raspberry Pi1 Model B、Raspbian 4.1.7+(NOOBS 1.4.2をダウンロードしてインストール)。

2.javascriptでGPIOを操作する方法を知る

 javascript(Node.js)でGPIOを操作するには、Web各所でいろいろ調べたところ、
(1)fsモジュールを使って/sys/class/gpioを書き換える
(2)wirirngPi等のGPIO操作ライブラリとNode.jsのchild_processモジュールを使う
など、いろいろ方法があることが分かった。そこで、まずは(1)の方法でやってみたが、どうもパーミッションの関係上うまく動かせなかった。(GPIOを操作するにはSudoが必要なのだが、nodeがsudoできなかった。シンボリックリンクを貼るとかいろいろ試したがだめだった。)
そこで、(2)の方法でやることにする。参考にしたサイトは、http://tomowatanabe.hatenablog.com/entry/2013/01/21/221722

 参考サイトを見ながら、wiringPiのインストール。以下の3行。

git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

そして、GPIO7番ピン(ピンヘッダでは26番ピン)にLEDをつなぎ、以下のスクリプトを作成した。実行するとLEDが点灯し、1秒後に消えることを確認。

var exec = require('child_process').exec;

exec('gpio -g mode 7 out');
exec('gpio -g write 7 1');

setTimeout(function(){
        exec('gpio -g write 7 0');
}, 1000);
3.Node.jsでHTMLファイルを表示する方法を知る

 次に、HTMLファイルをNode.jsで表示する方法だが、こちらが非常に参考になった。そのサイトに従い、以下のようなHTMLファイルtest.htmlと、それを読み出し表示するスクリプトtest.jsを/home/pi/Desktopに作成。そして、スクリプトを実行し、ブラウザからアクセスしたところ、無事Hello World!が表示された。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>htmlのテスト</title>
    </head>
    <body>
        <h1>Hello World!</h1>
    </body>
</html>
var fs = require('fs');
var http = require('http');

function serveron(request, response) {

        fs.readFile('test.html', 'utf-8', readFileCallback);

        function readFileCallback(err, data){
            response.writeHead(200, {'Content-Type': 'text/html'});
            response.write(data);
            response.end('');
        }
}

var server = http.createServer();

server.on('request', serveron);

server.listen(8124);
4.Node.jsで、クエリを取得する方法を知る

 Node.jsでクエリを取得する方法としては、http://onlineconsultant.jp/pukiwiki/?node.js%20GET%20POST%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8Bが参考になった。これに従い、以下のようなテストスクリプトを作成。HTMLはフォームのボタンを押すと、テキストボックスの文字が送信される。これを実行したところ、コンソールにPOSTされたメッセージ {test: 'abc'} が表示された。なお、スクリプトの7行目のifは、Chromeが1度に2回リクエストを送るため2回目を回避する処理。本題とは関係ないが、こちらを参考に入れた。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>queryのテスト</title>
    </head>
    <body>
        <form method="POST">
                <input type="text" name="test" value="abc">
                <input type="submit" value="submit">
        </form>
    </body>
</html>
var qs = require('querystring');
var fs = require('fs');
var http = require('http');

function serveron(request, response) {

        if (request.url == '/favicon.ico'){
                return;
        }

        console.log(request.method);

        if (request.method == 'POST'){
                var body = '';
                request.on('data', requeston);
                function requeston(data){
                        body += data;
                }
                request.on('end', requestonend);
                function requestonend(){
                        var query = qs.parse(body);
                        console.log(query);
                }
        }

        fs.readFile('test.html', 'utf-8', readFileCallback);

        function readFileCallback(err, data){
                response.writeHead(200, {'Content-Type': 'text/html'});
                response.write(data);
                response.end('');
        }
}

var server = http.createServer();

server.on('request', serveron);

server.listen(8124);

まとめと今後の課題

 Raspberry Pi で、Node.jsでGPIOを操作するための準備ができた。次回は、これらを組み合わせてGPIOを操作してみたい。

概要

 Raspberry Pi で、Node.jsをインストールし、Webサーバーを起動することができた。


背景と目的

 とある事情により、Raspberry Piでjavascriptを動かす必要が出てきた。そこで、Node.jsをインストールし、Webサーバーを立ち上げるところまでやってみる。


詳細

1.情報収集

 まずは、Web各所で情報収集。参考として、
参考1:http://usicolog.nomaki.jp/engineering/raspberryPi/raspberryPi_Nodejs.html
参考2:http://liginc.co.jp/web/programming/node-js/85318
あたりがよさそうだったので、これらの方法に従って進めることにした。

2.Node.jsのインストールまで

 Node.jsのインストールまでは、参考1の方法にのっとり、nodebrewをインストールしたあと、Node.jsをインストールした。バージョンはv0.10.28。ただし、expressというフレームワークは今は必要ないので省略。下の図が、インストール完了してバージョン確認までしたところ。普通にやれば10分以内で終わるだろう。

node院トール完了
図2 Node.jsのインストールが完了したところ

参考

wget http://nodejs.org/dist/v0.10.26/node-v0.10.26-linux-arm-pi.tar.gz
tar zxvf node-v0.10.26-linux-arm-pi.tar.gz
cd ./node-v0.10.26-linux-arm-pi
ls ./bin/
sudo cp -r * /usr/local/
3.テストスクリプトの作成

 次に、早速Webサーバーとして動かすため、テストスクリプトを作成。これは参考2にのっとり、以下のようなスクリプトを書いた。

var http = require('http');
 
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8124);

 そして、以下のコマンドで、スクリプトを実行。

node /home/pi/Desktop/test.js
4.動作確認

 LAN内のPCから、http://ラズパイのIPアドレス:8124にアクセスしたところ、無事Hello worldの文字が表示された。ちゃんとWebサーバーが動いているらしい。


まとめと今後の課題

 Raspberry Pi で、Node.jsをインストールし、Webサーバーを起動することができた。今後は、GPIOでも制御してみようと思う。

このページのトップヘ