Google Cloud IoT CoreでMQTTを試す

# 動機

以前、[AWS IoTを触った](https://qiita.com/h-sakano/items/f5cac9e1e81f93fc9277)が、
会社の基幹システムがGCPを使用する予定なので、GCPの同系統のサービスを試してみることにした。

# 目標

Google Cloud IoT Coreを使用し、Raspberry Piから、
MQTTプロトコルで[Cloud PubSub](https://cloud.google.com/pubsub/overview?hl=ja)にメッセージをパブリッシュする。

# MQTTについて

パブリッシュ・サブスクライブ方式のプロトコル。
[IBMのページ](https://www.ibm.com/developerworks/jp/iot/library/iot-mqtt-why-good-for-iot/index.html)がよくまとまっている。

# GCP側の準備

プロジェクトを作成し、「APIとサービス」から「Google Cloud IoT API」を有効化する。

## 端末レジストリの作成

メニューから「IoT Core」を選択すると、「端末レジストリ」の作成画面となる。

パラメータ|値
---|---
レジストリID|任意の値
Cloudリージョン|asia-east1
プロトコル|MQTT, HTTP
テレメトリーのトピック|events
デバイス状態のトピック|state

![スクリーンショット 2017-11-20 23.28.48.png](https://qiita-image-store.s3.amazonaws.com/0/172314/0ec34a26-8503-7138-1858-f475c645e927.png)

上記画面が出るので「続行」を選択する。

## 端末の追加

![スクリーンショット 2017-11-20 23.30.36.png](https://qiita-image-store.s3.amazonaws.com/0/172314/96cbde61-ec97-f84b-3873-9f46ccc6f30b.png)

端末の追加をクリック。
なお、今回はRaspberry PiをIoT端末として追加する。

### パラメータの入力

パラメータ|値
---|---
端末ID|任意
端末の通信|許可
公開鍵の形式|後述
公開鍵の値|後述
公開鍵の有効期限|省略(設定しない)
端末メタデータ|省略(設定しない)

### 公開鍵の登録

[公式ドキュメント](https://cloud.google.com/iot/docs/how-tos/credentials/keys?hl=ja&_ga=2.206706259.-1539408934.1508392647)を参考に、Raspberry Piにて公開鍵を作成する。
`openssl`を使用するので、インストールされてない場合はインストールする。

```.sh
$ openssl genrsa -out rsa_private.pem 2048
$ openssl rsa -in rsa_private.pem -pubout -out rsa_cert.pem
```

`rsa_cert.pem`の内容を「公開鍵の値」に入力する。
`rsa_private.pem`は端末側に配置して使用する。

# Raspberry Pi側の設定

## Python環境を準備

https://qiita.com/h-sakano/items/cb8df027b81acd78bd77

## サンプルコードをダウンロード

[こちらから](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/iot/api-client/mqtt_example)MQTTクライアントのサンプルをダウンロードし、端末に配置。

### このサンプルについて

内部でMQTTを使用している。
特にソースコードを弄らなければqos1でメッセージがパブリッシュされる。
また、クライアント証明書が必要なので、以下のコマンドで証明書をRaspberry Piに配置しておく。

```
$ wget https://pki.goog/roots.pem
```

## 必要なライブラリ等をインストール

```.sh
$ sudo apt-get install -y build-essential libssl-dev libffi-dev
$ sudo pip install -r requirements.txt
$ sudo pip install google-api-python-client
$ wget https://pki.goog/roots.pem
$ ls
cloudiot_mqtt_example.py  requirements.txt  rsa_private.pem	roots.pem
```

## トピックにメッセージをパブリッシュ

```
$ python cloudiot_mqtt_example.py --registry_id=iot-gateway --project_id=my_project --device_id=gateway1 --algorithm=RS256 --private_key_file=./rsa_private.pem --cloud_region=asia-east1
Creating JWT using RS256 from private key file ./rsa_private.pem
Publishing message 1/100: 'iot-gateway/gateway1-payload-1'
('on_connect', 'Connection Accepted.')
on_publish
Publishing message 2/100: 'iot-gateway/gateway1-payload-2'
on_publish
Publishing message 3/100: 'iot-gateway/gateway1-payload-3'
on_publish
Publishing message 4/100: 'iot-gateway/gateway1-payload-4'
on_publish
Publishing message 5/100: 'iot-gateway/gateway1-payload-5'
on_publish
Publishing message 6/100: 'iot-gateway/gateway1-payload-6'
on_publish
Publishing 
```

## トピックをサブスクライブ

```
$ gcloud beta pubsub subscriptions create --topic events my-subscriptions
$ gcloud beta pubsub subscriptions pull --auto-ack my-subscriptions
┌────────────────────────────────┬─────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│              DATA              │    MESSAGE_ID   │                                                                   ATTRIBUTES                                                                   │
├────────────────────────────────┼─────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ iot-gateway/gateway1-payload-1 │ 173994752831401 │ deviceId=gateway1 deviceNumId=3104791428628451 deviceRegistryId=iot-gateway deviceRegistryLocation=asia-east1 projectId=factory-iot subFolder= │
└────────────────────────────────┴─────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```

# まとめ

Google Cloud IoT CoreとRaspberry Piを使用して、PubSubにメッセージを送信することができた。
次は取得したデータを閲覧したりできるよう、PubSubと他サービスの連携を行っていきたい。