CrossBridge Lab

技術ネタ、デバイスネタを...

Google Home と Android ThingsでLチカする

今回はGoogle HomeAndroid ThingsでLチカする方法を解説します。

Google Homeとは

 Google HomeとはGoogleが開発したスマートスピーカーです。2016年11月にアメリカで発売されましたがしばらく日本では買うことができず、2017年10月にようやく日本でも発売されました。AmazonスマートスピーカーであるEchoに対抗してか、セールも行われ思わず買ってしまった人も多いのではないでしょうか。  Google Homeはタッチパネルやキーボードなどの入力装置は持たず、基本的に話しかけることで操作します(一応、本体上部を触って音量の操作などができる)。話しかけることで天気や交通情報を教えてくれたり、音楽を再生したりすることができます。

store.google.com

Android Thingsとは

 次にAndroid ThingsですがこちらもGoogleが開発したもので、IoT向けのプラットフォームとして発表したOSなどを含むソフトウェア群です。IoT機器向けの開発を行う場合、通常は組込機器向けのシステム設計が必要ですが、Android Thingsがその辺りのことを隠蔽してくれるので組込エンジニア(組込系の会社)以外もIoT機器関連の開発に手が出しやすくなるということがAndroid Thingsを使うメリットの一つではないでしょうか。

developer.android.com

 Android Thingsはいくつかのデバイスに対応していますが、日本ではRaspberry Pi3(ARMプロセッサを搭載したシングルボードコンピュータ)を購入するのが1番確実です。

今回の登場人物たち

 さて、本題に入っていきますがまずは今回の登場人物たちを整理しておきます。

  • Google Home
  • Android Things with ブレッドボード / LED
  • IFFFT
  • Firebase Realtime Database

 大まかな流れとしては以下の図の通りです。裏方にIFFFTとFirebase Realtime Databaseを使うことでお手軽にGoogle HomeAndroid Thingsを連携させることができます。

f:id:crossbridge-lab:20171220120041p:plain

 Lチカ、つまりLEDをチカチカさせるということで半田ごてを使った電子工作なイメージを思い浮かべるかもしれませんが、今回ハンダ付けは必要ありません。ブレッドボードという穴の空いた実験用の基盤を使うことでハンダ付けをせずに穴にLEDやジャンパ線などを差し込むだけで完成します。

f:id:crossbridge-lab:20171220120103j:plain

Android Things単体でLチカする

 まずはAndroid Things単体でLチカしてみましょう。ここでは前述したRaspberry Pi3にAndroid Thingsがインストール済みであることを前提とします。インストールの仕方などはこのあたりを参考にしてください。

crossbridge-lab.hatenablog.com

プロジェクトを作成する

 Android Things向けアプリのプロジェクトを開発する際も通常のAndroidアプリと同様にAndroid Studioを使います。いつも通り新規プロジェクト作成の画面に進み、1番下のAndroid Thingsにチェックを入れることでAndroid Things向けアプリのプロジェクトを作成することができます。

f:id:crossbridge-lab:20171220120135p:plain

 Activityの種類を選ぶ画面ではEmptyActivityの方を選びます。

f:id:crossbridge-lab:20171220120157p:plain

 Android Things向けに作成した場合に通常のAndroidアプリと異なる点はdependenciesに以下の記述があることです。これによりAndroid Things向けのクラス群を使うことができるようになります。逆にそれ以外はほぼAndroidアプリと同じであり、通常のAndroidアプリ開発を行うときと同じように開発を行うことができます。

compileOnly 'com.google.android.things:androidthings:+'

PeripheralManagerServiceを使ってGPIOを操作する

 突然でてきたGPIOという単語ですが、General-purpose input/outputの略で日本語では「汎用入出力」となり、簡単に言うと他のデバイスに入力にも出力にも使える便利なデジタル信号の出入口です。今回は出力として使い、LEDに電力を流すことで点灯させるという使い方をします。入力として使うとセンサーを繋いで温度や明るさなどを得るという使い方ができます。

 Raspberry Pi3にはいくつかのGPIOがあります。Raspberry Pi3自体の仕様書を見てもよいですが、GoogleもRaspberry Pi3のピン配置を公開しておりアプリから利用する名前も記載されているのでこちらを見るのが良いでしょう。

 GPIOを使う際は PeripheralManagerService というクラスを使います。gpioList メソッドでGPIOの一覧が取得できるのでログに出力してみます。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // GPIOのリストを表示
        val service = PeripheralManagerService()
        for (gpio in service.gpioList) {
            Log.d(TAG, "gpio -> $gpio")
        }
    }

 次のように利用できるGPIOの名前が出力されます。今回は BCM17(11番ピン)BCM27(13番ピン)を使うことにします。

12-19 13:25:08.257 1819-1819/? D/ContentValues: gpio -> BCM10
12-19 13:25:08.257 1819-1819/? D/ContentValues: gpio -> BCM11
12-19 13:25:08.257 1819-1819/? D/ContentValues: gpio -> BCM12
12-19 13:25:08.257 1819-1819/? D/ContentValues: gpio -> BCM13
〜〜以下省略〜〜

 それでは実際にGPIOを利用します。手順は以下の通りです。

  1. 利用するGPIOの名前を指定して open する
  2. GPIOを出力で利用するのか入力で指定するのか指定する。出力の場合は初期値も合わせて指定する。
  3. 値を設定する
  4. 最後に忘れずに close する

 先ほどのコードの後に2つのGPIOの初期設定を行います。PeripheralManagerServiceクラスの openGpio メソッドに利用するGPIOの名前を指定します。Gpioクラスが取得できるので、setDirection メソッドで DIRECTION_OUT_INITIALLY_LOW (出力/初期値LOW) と設定します。onDestroyで忘れずに close メソッドを呼び出します。これを忘れるとアプリを終了しても他のアプリでこれらのGPIOを操作することができなくなってしまいます。

    val RED_LED_NAME = "BCM17"
    val YELLOW_LED_NAME = "BCM27"
    var redGPIO: Gpio? = null
    var yellowGPIO: Gpio? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // GPIOのリストを表示
        val service = PeripheralManagerService()
        for (gpio in service.gpioList) {
            Log.d(TAG, "gpio -> $gpio")
        }

        // GPIOにアクセスできるようにする
        try {
            redGPIO = service.openGpio(RED_LED_NAME)
            yellowGPIO = service.openGpio(YELLOW_LED_NAME)

            // GPIOの設定を出力、初期値LOWにする
            redGPIO?.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
            yellowGPIO?.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
        } catch (e: IOException) {
            Log.e(TAG, "error", e)
        }
    }
    
    override fun onDestroy() {
        super.onDestroy()

        try {
            redGPIO?.close()
            yellowGPIO?.close()
        } catch (e: IOException) {
            Log.e(TAG, "error", e)
        }
    }

 これでGPIOを利用する準備が整いました。ゴールはGoogle Homeから操作することですが、まずは画面にSwitchを表示してSwitchをオン/オフしたらLEDが点灯/消灯するようにします。Gpioクラスのvalueにture/falseを設定することで出力のオン/オフとなります。その結果、LEDが点灯/消灯します。これでGPIOの操作は完璧です。(GPIOを入力で使う場合はアクティブローとアクティブハイの設定などが必要になりますがまたの機会に)

        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        binding.switchRed.setOnCheckedChangeListener{view, isChecked ->
            if (isChecked) {
                redGPIO?.value = true
            } else {
                redGPIO?.value = false
            }
        }

        binding.switchYellow.setOnCheckedChangeListener{view, isChecked ->
            if (isChecked) {
                yellowGPIO?.value = true
            } else {
                yellowGPIO?.value = false
            }
        }

IFFFTとFirebase(Realtime Databese)を使ってGoogle HomeAndroid Thingsを連携する

 Android Things単体でLチカができるようになったので次はGoogle Homeから操作できるようにします。Google Homeとの連携は今回はIFFFTを使います。 GoogleのDialogflow https://dialogflow.com/ と比較して細かい設定ができないことや、タイムラグが大きいことなど欠点もありますが簡単に使うことができるよう大きなメリットがあります。

Firebaseのプロジェクトを作成してデータベースを準備する

 IFFFTからWebhookでデータベースの値を変更し、AndrodThingsではその値の変化を監視します。Firebaseのプロジェクトを作成します。プロジェクトを作成したら直下に redyellow というキーを作っておきます。

f:id:crossbridge-lab:20171220120222p:plain

 本来はよろしくないのですがセキュリティ(ルール)の設定を変更します。IFFFTからWebhookで書き込みできるように認証なしでアクセスできるルールとします。この設定にするとURLを知っていれば自由に読み書きできてしまうので注意してください。実際に何か実用的なものを作って運用する際にはセキュリティを意識しましょう。

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

 これで https://hoge.firebaseio.com/red.json https://hoge.firebaseio.com/yellow.json というアドレスでデータを書き込むことができるようになりました。(hogeの部分は各自作成したプロジェクトに置き換えてください)

IFFFTのAppletを作成する

 トリガーとなるthisにはGoogle Assistantレシピを設定します。Google Assistantレシピの中の Say a phrase with a text ingredient を選択し、What do you want to say に 赤色 $ と入力します。これは 赤色 という言葉をトリガーとし、それに続く言葉を変数としてtahtで使うようにすることを意味します。

f:id:crossbridge-lab:20171220120237p:plain

 トリガーを受けて動作するアクションであるthatにはWebhooksを設定します。URLにはFirebaseのURL https://hoge.firebaseio.com/red.json を入力し、PUTでbodyに "{{TextField}}" を入力します。

f:id:crossbridge-lab:20171220120414p:plain

 これを黄色用も同じように作成します。さて、これでGoogle Homeに「赤色(黄色) ほげほげ」と話しかけるとほげほげの部分がFirebaseのデータベースに保存されるようになりました。

アプリでRealtime Databaseの値を監視する

 最後にアプリでRealtime Databaseの値を監視し、その値によってLEDを点灯/消灯させる処理を実装します。Firebaseの公式ドキュメントの手順通りにbuild.gradleへの追記とjsonファイルを配置してFirebaseを扱えるようにしておきます。

 onCreateでGPIOの設定をした後に次のように記述します。キー red の値が変化した際に、バリューを見てLEDを点けるか消すかの判断をしています。

        // Database
        val database = FirebaseDatabase.getInstance()
        val redRef = database.getReference("red")
        redRef.addValueEventListener(object: ValueEventListener {
            override fun onCancelled(p0: DatabaseError?) {
            }

            override fun onDataChange(snapshot: DataSnapshot?) {
                val value = snapshot?.getValue(String::class.java)
                Log.d(TAG, " $value")

                val word = value?.replace(" ", "")
                when (word) {
                    "オン", "音", "つけて" -> {
                        redGPIO?.value = true
                        binding.switchRed.isChecked = true
                    }
                    "オフ", "消して" -> {
                        redGPIO?.value = false
                        binding.switchRed.isChecked = false
                    }
                }
            }
        })

 ポイントはバリューの文字列からスペースを除いている点です。今回「つけて」と発音したときに「つけ て」とスペースが入ってきたためです。

f:id:crossbridge-lab:20171220172736p:plain

また、「オン」と発音しても「音」と期待通りの文字列が入って来なかったためwhenで分岐させる際の値として「音」も指定しています。音声入力は期待通りの読みで入ってくるとは限らないためできるだけ多くの文字列で判断した方が良いでしょう。

 今回はとりあえずLEDを点灯させただけですが、赤外線LEDを使ってエアコンのリモコン代わりにしたり、センサーと組み合わせたりとかアイデア次第で使い方が広がると思います。皆さんも組み込みの開発の深い知識がなくても手軽に始めることができるAndroid Thingsを活用してみては如何でしょうか。

 最後にデモしてる動画は置いておきます。

youtu.be

 

Android ThingsをRaspberry Pi 3にインストールする

Android Thingsとは

Android ThingsはGoogleのIoT向けのプラットフォームとして発表されました。開発者は、このプラットフォームとAndroid API、様々なGoogleのサービスを利用することで各種のスマートデバイスを開発することができます。

f:id:crossbridge-lab:20171210162524p:plain

Android Thingsを動かすことができるハードウェア

ハードウェアの一覧はこちらにあるとおり、以下の4つです。

  • NXP Pico i.MX7D
  • NXP Pico i.MX6UL
  • NXP Argon i.MX6UL
  • Raspberry Pi 3

日本での手に入れ易さを考えると、現実的にはRaspberry Pi 3一択かもしれません。

Raspberry Pi 3を準備する

Raspberry Pi 3本体が必要なのは当然ですがその他にも幾つか揃えなければならないものがあります。Raspberry Pi 専用のタッチパネル付きの液晶が手に入ればそれが一番ですが、HDMI出力が可能なのでPCのディスプレイなどで代用することもできます。今回はPCのディスプレイを使うことを前提としています。

  • Raspberry Pi 3本体
  • MicroUSB端子から5V2.5A以上(3Aならなお良し)が供給できる電源アダプタ
  • 8GB以上のマイクロSDカード
  • HDMIケーブル
  • USBキーボード
  • USBマウス

Raspberry Pi 3にAndroid Thingsをインストールする

それではRaspberry Pi 3にAndroid Thingsをインストールしてみましょう。手順は以下の通りです。

  1. Android Thingsのシステムイメージを作成する
  2. microSDカードにシステムイメージを書き込む

すでにRaspbianなどでRaspberry Pi 3を使っている人であれば特にハマることもなく進めることができるかと思います。

1. Android Thingsのシステムイメージを作成する

Android Thingsのシステムイメージは (Android Things Console)https://partner.android.com/things/console で作成します。初めてAndroid Things Consoleにアクセスしたときは規約に同意を求められるので内容を確認して問題がなければ同意します。

規約に同意すると次の画面が表示されるので「CREATE A PRODUCT」ボタンをクリックします。

f:id:crossbridge-lab:20171210164410p:plain

ProductNameに何かしら判別できる名前を入力し、SOM typeはRaspberry Pi3 を選択してほかはそのままで下の「CREATE」ボタンをクリックします。

f:id:crossbridge-lab:20171210164421p:plain

しばらくすると次の画面に変わるので「FACTORY IMAGES」タブをクリックします。

f:id:crossbridge-lab:20171210164450p:plain

「1. Upload and select a bundle」はEmpty bundleを選択したまま「NEXT」をクリックします。

「2. Select your Android Things version」はlatestのものを選択します。今回は一種類しか表示されなかったのでそのまま「NEXT」をクリックします。

「3. Name your build configuration」には今回の設定を判別できる名前を入力し、「CREATE BUILD」ボタンをクリックします。

f:id:crossbridge-lab:20171210164856p:plain

しばらくするとイメージファイルが完成し、ダウンロード可能になります。「Download」をクリックしてダウンロードします。ZIPファイルがダウンロードされるので解凍しておきます。

f:id:crossbridge-lab:20171210165243p:plain

2. microSDカードにシステムイメージを書き込む

ダウンロードしたZIPファイルを解凍したら iot_rpi3.img というファイルができたはずです。これがイメージファイルになるのでDDコマンドでマイクロSDカードに書き込みます。

$ sudo dd bs=1m if=iot_rpi3.img of=/dev/rdisk2

of= で指定するデバイス名は環境に合わせて変更する必要があります。macOSであればディスクユーティリティで確認するのも良いでしょう。

f:id:crossbridge-lab:20171210184616p:plain

書き込みは時間がかかるのでコーヒーでも飲みながら待ちます。しばらくすると以下のような表示がでて完了です。

4352+0 records in
4352+0 records out
4563402752 bytes transferred in 316.186078 secs (14432649 bytes/sec)

Raspberry Pi 3にSDカードを挿入して起動する

先ほどシステムイメージを書き込んだマイクロSDカードをRaspberry Pi 3のカードスロットに挿入して電源を入れます。ブートアニメーションがしばらく表示されたあと起動します。次のような画面になれば無事起動完了です。

f:id:crossbridge-lab:20171210185430p:plain

【Unity】C#で乱数を生成する

UnityではRandomクラスは.NET FrameworkのSystemではなく、UnityEngineの中にあるため微妙にメソッドが異なる模様(Nextメソッドが使えない)

0〜1.0までの浮動小数点(float)を得る

float value = Random.value;

XからYまでの整数(int)を得る

整数の場合、第2引数で与えた値は返ってくる範囲には含まれません(exclusive)。

int value = Random.Range(X, Y + 1)

XからYまでの浮動小数点(float)を得る

浮動小数点の場合、第2引数で与えた値は返ってくる範囲には含まれます(inclusive)。 整数の場合と異なるので要注意です。

float value = Random.Range(X, Y)