RaspberryPi3+AndroidThingsでMonacaからLチカしてみた


はじめに

みなさんこんにちは。
Monaca使ってますか?モバイルアプリ作ってますか?
近年モバイル端末の普及に加え、IoTが急成長していますね。

そんな中、GoogleがIoT向けAndroid=AndroidThingsを発表しました。
そして私の手元には、RaspberryPi3が。

AndroidThingsはRaspberryPi3をサポートしています。
GoogleはAndroidThingsのDeveloper Preview 5でWebViewを搭載してきました。

・・・あれ?それってCordova使ったらHTML+JavaScriptで開発もできるようになったってこと?
・・・ん?Monacaも動くんじゃね?
はっ!?MonacaでLEDチカチカできるんじゃね?

はい。やってみました。

注意

Monacaにカスタムプラグインを搭載する必要があるため、Monacaは有償プランにしておく必要があります。
フリーでやってみたい!と言う方はMonacaではなく純粋にCordovaでチャレンジしてみてください。

準備

まずはRaspberryPi3を用意します。←当たり前

AndroidThingsの公式サイトから最新のイメージを入手します。
→執筆時点でDeveloper Preview 6が最新でした。

起動方法やLED回路の配線なんかはAndroidThingsでLEDチカチカさせてみてる方の記事を確認してみてください。

やってみた

RaspberryPi3に搭載されているGPIOにネイティブアクセスする必要があるため、Cordovaプラグインが必要になります。
→ググりましたが当然ありません。。AndroidThingsが提供しているAPIから超絶簡単にGPIO制御ができるようなので、サクッとCordovaプラグイン化しちゃいます。

Cordovaプラグイン作成

PeripheralManagerServiceからGpioオブジェクトをopenGpio(String)で取得して、setValue(boolean)で電流をON/OFFできるようです。
これらをJavaScriptから呼び出せるように、CordovaPluginをオーバーライドし execute() を実装します。

GpioPlugin.java
package org.apache.cordova.things;

/* 中略 */

public class GpioPlugin extends CordovaPlugin {

    private PeripheralManagerService service = new PeripheralManagerService();

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

        if ("openGpio".equals(action)) {
            String name = args.length() > 0 ? args.getString(0) : null;
            Integer direction = args.length() > 1 ? args.getInt(1) : null;
            return openGpio(name, direction, callbackContext);
        } else if("setValue".equals(action)) {
            String name = args.length() > 0 ? args.getString(0) : null;
            Integer value = args.length() > 1 ? args.getInt(1) : null;
            return setValue(name, value, callbackContext);
        }

        return false;
    }


    // GPIOピンをオープンします
    private boolean openGpio(String name, Integer direction, CallbackContext callbackContext) {
        try {
            Gpio gpio = service.openGpio(name);
            gpio.setDirection(direction);
            /* ここでは省略していますが、このあと取得したオブジェクトはキャッシュしておきます */
        } catch(IOException e) {
            return false;
        }
        callbackContext.success();
        return true;
    }

    // GPIOピンの電流をON/OFFします
    private boolean setValue(String name, Integer value, CallbackContext callbackContext) {

        try {
            /* ここでは省略していますが。GPIOオブジェクトをキャッシュから引き当てています */
            gpio.setValue(value != 0);
        } catch(IOException e) {
            return false;
        }
        callbackContext.success();
        return true;
    }
}

サンプルで作成したものをGitHubで公開しています。
https://github.com/ShinyaSuefusa/cordova-plugin-gpio

なお、AndroidThingsはJava 8でコンパイルする必要があります。
Monacaがビルドで使用しているJavaSDKは8ですがCordovaの標準設定では6相当となっているようです。
これを8に引き上げるため、build-extras.gradleを追加しています。
※AndroidThings用Cordovaプラグインを開発する場合は必須の設定になると思います。

build-extras.gradle
android {
    defaultConfig {
        jackOptions {
            enabled true
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

また、AndroidThingsのAPIを使用する場合、AndroidManifest.xmlにuses-librayを書いておく必要があります。
これがないとRuntimeExeptionが発生します!
plugin.xmlに下記を追加してください。

plugin.xml
        <config-file target="AndroidManifest.xml" parent="/manifest/application">
            <uses-library android:name="com.google.android.things"/>
        </config-file>

MonacaでLチカ用アプリを作る

ここからが本題です。
Monacaで空のプロジェクトを作成し、先ほど作成したCordovaプラグインをインポートします。

HTMLの画面にはシンプルにONとOFFのボタンを用意しました。

<body>
  <ons-page ng-controller="GpioController as vm">
    <ons-toolbar>
      <div class="center">Raspberry Pi 3 GPIO</div>
    </ons-toolbar>

    <div class="content" style="margin: 10px;">
      <button ng-click="vm.onClick(1)">ON</button>
      <button ng-click="vm.onClick(0)">OFF</button>
    </div>
  </ons-page>
</body>

JavaScriptからはdevicereadyイベントが発火してから、GPIOをオープンします。
ON/OFFボタンのng-clickイベントから、GPIOの電流をON/OFFするよう、setValue() を呼び出します。
ここではGPIO17ピンを使用しています。

    var gpio;
    var PIN_NAME = "BCM17";
    ons.bootstrap()
      .controller('GpioController', function() {
        var vm = this;
        vm.onClick = function(value) {
          gpio.setValue(PIN_NAME, value);
        };
      });
    ons.ready(function() {
      console.log("Onsen UI is ready!");
      gpio = cordova.plugins.gpio;
      gpio.openGpio(PIN_NAME, function() {
        console.log("success open "+PIN_NAME);
      });
    });

ビルドしてapkファイルが出来上がったら、adbコマンドを使用してAndroidThingsにインストールします。

$ adb connect 192.168.x.x
$ adb install xxxxxx.apk

起動してみましょう。

$ adb shell am start -n com.example.helloworld/.MainActivity

しばらく待つと、WebViewが起動します。

AndroidのWebViewなので、もちろんPC側からChromeでデバッグできます。

チカチカを楽しむ

ボタンを好きなだけ押してください。
LEDがまぶしいですね。

あとがき

Javaネイティブで開発するより圧倒的に生産性が高く、また電子モジュールへのアクセスは汎用的なプラグインにしてしまえば、あとは学習コストの低い言語でもセンサーや電子機器を制御することができるようになったと感じました。
また、スマホとは違い、画面は無くても良いですし、あってもマウスやタッチパネルを組み合わせて入力できる柔軟性があります。
手元にある電子工作キットには赤外線リモコンがついていて、リモコンでMonacaアプリ操作とかできますね!

インターネット環境が整っていれば、Monacaの標準的な開発スタイルでセンサーや入出力モジュールとクラウドがあっという間に繋がります。
今回は試していませんが、Websocketを通じてリモートでデバイスを制御・・・なんてことも。
→TODO:記事書くっきゃないでしょ!

デバイスの制御でC言語を使う時代はもう終わりなのですね。

IoTの開発が捗りますね!

p.s.

アシアルさん、見てますか?
IoT開発のプラットフォームとしてのMonacaも是非推進していただきたい!!