EC21-JとSORACOM IoT SIMによりGoogle IoT CoreでMQTT接続を行うまでの全過程の記録

# 記事の概要
通信モジュールEC21-J Mini PCIeとSORACOM IoT Simを用いて、Google Cloud Platform（以下、「GCP」と略）に構築したGoogle IoT CoreでMQTT接続による通信を行ってみました。

そこに至るまでの全過程、モジュールの購入から最後のMQTT接続を実行するまでの記録を公開します。

記事の内容に疑問点があれば、お気軽にコメント欄、ツイッターなどにお問い合わせください。
また記事内容に間違いなどがあれば、ご指摘いただけると助かります。

## 参照
- [LTE Cat.1 対応モデム「EC21-J Mini PCIe」の GNSS 搭載モデルを販売開始](https://blog.soracom.jp/blog/2019/08/29/ec21j-minipcie-with-gnss/)
    - 開発ボードのセッティングからGNSS動作を確認するところまで解説しています。
- [Arduino で SORACOM SIM を使ってなるべく安く通信する方法](https://bearmini.hatenablog.com/entry/2017/06/01/205959)
    - EC21-J Mini PCIeでSORACOM Harvest にデータを送る方法を解説しています。
- [SORACOM Beam を使用して Google IoT Core と MQTT 接続する](https://dev.soracom.io/jp/start/beam_google_iot_core/)

# 1. ハードウェアの準備

## EC21-J Mini PCIeの準備
以下のQuectel社製の通信モジュールEC21-J Mini PCIeを使用します。
（Quectel社へのリンクはユーザー登録しないと見れません。登録は無料になります。）

https://www.quectel.com/product/ec21minipcie.htm

これは[EC21-Jモジュール](https://www.quectel.com/product/ec21.htm)にPCIeソケットやアンテナ端子を取りつけたLTE Cat.1 通信モジュールです。
末尾のJはJapanのことで、日本用の技適を取得済みを意味します。
末尾にJがつかないEC21は、日本での使用が違法になるのでご注意ください。

今回はGNSS機能付きのEC21-J Mini PCIeを使用します。
GNSSはグローバル衛星測位システムのことで、GPSもその1種です。

EC21-J Mini PCIeはSORACOMのIoTストアもしくはSORACOM ユーザーコンソールから購入できます。

https://soracom.jp/products/module/ec21-j-gnss/

他にもGNSS機能のないEC21-J Mini PCIeや、UC20-G Mini PCIe、BG96 MiniPCIeも販売しています。

## 開発ボード Mini PCIe EVBKITの準備
https://www.quectel.com/product/minievb.htm

Mini PCIe EVBKITはPCIeソケットを備えた開発ボードです。
PCIeソケットにQuectel社のPCIe端子付きの通信モジュールを取り付けることで、簡単にPCによる制御が行えます。

今回はEC21-J Mini PCIeを取り付けます。

こちらもSORACOMのIoTストアもしくはSORACOM ユーザーコンソールから購入できます。

https://soracom.jp/products/module/mini-pcie-evbkit/

PCIeソケットなどの部品を購入して、治具を自作することも可能と思いますが、制作に要する時間（部品選定、販売店検索、発注、制作、動作試験、修正）を時給換算で見積もると、開発ボードを購入した方が安上がりでした。
手作りを楽しみたい場合や、時間に余裕がある場合は、自作してもいいと思います。

### UART通信方法
後述するEC21-Jの操作を行う為に、EC21-JとUART通信を行わないといけません。
開発ボードを用いれば、PCからEC21-JとUART通信を行えます。

ドライバーは開発ボード付属のCDもしくは[Quectelのサイト](https://www.quectel.com/product/ec21.htm)の「Download」の「USB Drivers」からダウンロード済みとします。
複数のドライバーがありますが、私は以下のフォルダのexeファイルを実行しました。（必須ではないものも実行しているかもしれません。）

Quectel_LTE_Windows_USB_Driver_V1.0.0
EC21&EC25_WinCE6.0_USB_DriverV1.0
Quectel_BG96_Windows_USB_Driver_V1.0

次に付属のUSB-RS232ケーブルを用いて、開発ボードとPCを接続します。
秋月電子などで販売しているUSB-RS232ケーブルでも問題ないと思います。

[ＦＴ２３２　ＵＳＢシリアル変換ケーブル　ＶＥ４８８](http://akizukidenshi.com/catalog/g/gM-08343/)
[ＵＳＢシリアル変換アダプタ](http://akizukidenshi.com/catalog/g/gM-06812/)

USBとシリアルケーブルをPCに接続し、開発ボードの電源ONにして、デバイスマネージャーで確認すると、以下のようにUSBポートが3つ、シリアルポートが1つ表示されます。

<img width="60%" alt="デバイス確認.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/8ae5ad7c-a46a-a168-d1a8-7bc99da5963f.png">


TeraTermなどのターミナルソフトを開いて、COM Port（私の場合はCOM9）を選択し、通信設定を115200bpsにすればPCからUART通信できます。

<img width="40%" alt="TeraTerm設定1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/f2e1700c-4194-f992-92b2-bfd3e4d9ab13.png">
<img width="40%" alt="TeraTerm設定2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/43791983-90da-7dcd-7659-09093e7e5db9.png">
<img width="40%" alt="TeraTerm設定3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/193e62ec-e948-d450-5245-52dbe31b09c1.png">

### アンテナの取り付け
GNSSアンテナをモジュールのアンテナ端子の真ん中GNSSに取り付けます。
2本のアンテナは両端のアンテナ端子MAINとDIVに取り付けます。
<img width="60%" alt="開発ボード.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/f61d53eb-1a13-72d2-d0b8-e3e2c3ca048b.jpeg">


## SORACOM IoT SIMの準備
SORACOM IoT SIMを用いるとIoTに適したSORACOMのネットワークサービスを安価に利用できます。
3G/LTE に対応したデータ通信、データ転送、データ管理、データの可視化と共有など様々なサービスがあります。

https://soracom.jp/services/air/cellular/

以下のチュートリアル通りに行えば簡単に利用開始できます。

https://dev.soracom.io/jp/start/begin_soracom/


SORACOMのIoTストアもしくはSORACOM ユーザーコンソールから購入できます。
今回は特定地域向け IoT SIM (plan-D)標準サイズを使用します。

https://soracom.jp/products/sim/


SIMはスイッチサイエンスなどでも購入できます。
https://www.switch-science.com/catalog/3960/
https://www.switch-science.com/catalog/5884/

### SIMの登録
SORACOMにはアカウント登録済みとして以下の話を進めます。


開発ボード一式およびSIMをSORACOMから購入した場合は、ユーザーコンソールの「Menu」→「発注」から注文品のステータスの「受け取り確認」をクリックするだけでSIMが登録されます。

<img width="40%" alt="SORACOM_SIM登録.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/6f9834b5-83bc-71d9-c33d-9ba1cf40c952.png">

<img width="50%" alt="SORACOM_SIM登録2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/9e8c40aa-e753-c40e-2fa4-62474b20838c.png">


以下のマニュアルに従ってグループ作成します。
[SIM のグループ管理](https://dev.soracom.io/jp/start/console/#group)

<img width="50%" alt="SORACOM_SIM登録3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/08eead1f-ab7c-b902-1648-c77e02a00cf5.png">

対象の先頭セルのボックスにチェックを入れて、操作から利用開始を選択すれば、通信ができるようになります。

課金も開始されますので、まだ利用する予定のない方はご注意ください。
もっとも、基本料金は10円／1日と安く、開発ボードの無料クーポン分でしばらくは課金されないので、あまり気にすることもないと思います。

<img width="40%" alt="SORACOM_SIM登録4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/110c2661-0681-124d-c22f-8d4a4f124655.png">

<img width="40%" alt="SORACOM_SIM登録5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/af22a086-23d2-f365-3fcf-e74b029cd06b.png">



# 2. EC21-Jの動作確認
EC21-Jは、UART通信でATコマンドを送信することで操作できます。
今回はPCから操作しますが、いずれマイコンからのUART通信で制御したいと思います。

## EC21-JのUART通信確認
EC21-Jが動作しているかを確認します。先述した方法でターミナルでシリアルポートを開いてください。

まずは、自分の入力したコマンドが分かりやすいように入力エコーを有効にします。
エコーとは、送信した文字を、そのまま送り返してもらって受信することです。

```
ATE1
```

と入力してENTERを押せば、以降は自分の入力した文字も表示されます。
（エコーが無効ならば、入力しても画面には何も表示されません。）

次に、製品識別情報表示コマンド

```
ATI
```

を入力してください。
社名、製品名、Revisionの3行が表示されれば、EC21-Jと正常に通信できています。
<img width="80%" alt="ATIコマンド試験1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/c92d20d9-98c0-7128-2fe4-c198466d9a91.png">

## GNSSの動作確認
GNSSの動作を確認します。まずは電源ONに、開発ボードのNRT_STATUS LEDが点灯後に、以下のコマンドを入力してGNSSを起動します。

```
 AT+QGPS=1
```

起動に成功すればOKが返ります。
![GNSS試験1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/bc532625-da82-2127-356d-44603b4b3377.png)


GNSSの取得データは、TeraTermを新規に開いて、「Quectel USB NMEA Port」から確認してください。通信速度は4800bpsに設定します。
<img width="40%" alt="GNSS試験3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/0826c8e4-af6b-c5e8-e33a-84d66bbec95b.png">


以下のようにGNSSからの情報が表示されます。
<img width="10%" alt="GNSS試験4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/bfadd57f-1834-e937-d26c-68521fcbc5fb.png">

シリアル通信でも以下のコマンドでGNSSの位置情報を取得できます。

```
AT+QGPSLOC?
```

<img width="80%" alt="GNSS試験5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/ee262d1e-62f3-5d46-a4d0-6195955a37e6.png">


GNSSは以下のコマンドで停止できます、

```
 AT+QGPS=0
```
もしくは

```
 AT+QGPSEND
```

# 3. 通信試験
EC21-JとSIMを用いて、ネットワークに接続し、データ通信できるかを確認します。
以下の通信試験は、bearminiさんの記事「[Arduino で SORACOM SIM を使ってなるべく安く通信する方法](https://bearmini.hatenablog.com/entry/2017/06/01/205959)」を参照しました。

## AT+QCFG="roamservice"[,\<roammode\>[,\<effect\>]] 
ローミングを有効にします。
初期状態で有効かもしれませんが一応設定しておきます。
roammodeを2に設定すると「ローミング有効化」、effectを1に設定すると「即座に有効化」になります。
effectを省力すると、自動で「即座に有効化」の設定になります。

```
 AT+QCFG="roamservice",2,1
```

## AT+COPS=\<mode\>[,\<format\>[,\<oper \>[,\<Act\>]]] 

登録可能なオペレータ一覧を以下のコマンドで確認します。

```
AT+COPS=? 
```

また、現在登録されているオペレーターは以下のコマンドで確認します。

```
AT+COPS? 
```

<img width="90%" alt="ATCOPS1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/7a8c1487-c9a0-eac3-4cac-a83405162e7d.png">


私の場合は、既にオペレーターが登録済みだったので、設定は省略します。

もしAT+COPS?で何も表示されない場合は、手動で設定します。
AT+COPS=? で検索した登録可能なオペレータ一覧から選択して、以下のコマンドを実行します。
modeは1の手動選択に設定し、formatは2のGSM location area識別番号に設定し、operは各位の環境に合わせて選択ください。

```
AT+COPS=1,2,"44010"
```

設定後は、正常にオペレーターが登録されているか確認しておきます。

```
AT+COPS? 
```

## AT+QICSGP=\<contextID\>[,\<context_type\>,\<APN\>[,\<username\>,\<password\>)[,\<authentication\>]]] 

APN, username, password TCP/IP contextパラメータの設定を行います。

contextIDは1から16の任意の番号を設定し、context_typeは1のプロトコルタイプ：IPV4 に設定し、APNは"soracom.io"に設定し、usernameとpasswordは"sora"に設定し、authenticationは0の認証なしに設定します。

```
AT+QICSGP=1,1,"soracom.io","sora","sora",0
```

## AT+QIACT=\<contextID\>
PDP認証を行います。
AT+QICSGPで設定したcontextIDを指定することで、設定を有効化できます。


```
AT+QIACT=1
```

設定前後にAT+QIACT?を実行すると、設定実行後に有効化されていることが分かります。

<img width="50%" alt="ATQIACT.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/2545b6d5-962b-740b-855c-06803cc58d37.png">

ここまでの設定を行うと、SORACOMのユーザーコンソールにおいて、セッション状態がオンラインになってます。
<img width="80%" alt="ATQIACT2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/cdafe330-becf-f0fa-8372-a762d36c297b.png">

## SORACOM Harvestの設定
データ送信のテストを行う為にSORACOM Harvestを設定します。
SIMの所属するグループを選択し、SORACOM Harvest Data設定をONにして保存します。
1SIMあたり5円／1日の課金が発生するので、通信試験完了後はOFFに戻して保存するのを忘れないようにご注意ください。

<img width="30%" alt="Harvest1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/ad41cf10-6a7b-ca1d-7b98-7856cb0baad3.png">

<img width="50%" alt="Harvest2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/d84d9f22-b435-e73b-0eff-d7e327f3d8ad.png">


## AT+QIOPEN=\<contextID\>,\<connectID \>,\<service_type\>,\<IP_address\>/\<domain_name\>,\<remote_port\>[,\<local_port\>[,\<access_mode\>]] 
SORACOM Harvestを開きます。

```
AT+QIOPEN=1,0,"TCP","harvest.soracom.io",8514
```

## AT+QISEND=\<connectID\> 
AT+QIOPENで設定したconnectIDを指定してデータを送信します。

```
AT+QISEND=0
```

上記コマンド実行後、送信したいデータを入力してから、Ctrl+Zを入力するとデータが送信されます。
<img width="50%" alt="Harvest4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/adac015e-dc67-41ab-44c5-a25f84c38b24.png">


データが送信されているかを確認してみます。
使用したSIMにチェック入れてから、「操作」→「データを確認」を選択します。
<img width="50%" alt="Harvest5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/cd464fd0-9c0f-e502-4ab0-0abe68a75b77.png">

コマンド送信したのと同じデータが確認できます。
<img width="80%" alt="Harvest6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/c59d672d-e48c-d862-abe0-f36de4b9c462.png">

ネットワークと接続して通信できることが確認できました。

## AT+QICLOSE=\<connectID\> 
AT+QIOPENで設定したconnectIDを指定して接続を閉じます。

```
AT+QICLOSE=0
```

SORACOM Harvest Data設定をOFFに戻して保存し、通信試験を完了します。

# 4. Google IoT Core

##GCP側の設定
ここではGCPにアカウント登録済みとして、Google IoT Coreの作成します。

[SORACOM Beam を使用して Google IoT Core と MQTT 接続する](https://dev.soracom.io/jp/start/beam_google_iot_core/)の説明に従って作業します。

1: IoT Coreを開いてレジストリを作成
<img width="50%" alt="IotCore1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/aef659ba-471a-99f6-81ed-e2510387b75f.png">

2: レジストリID、リージョン、Cloud Pub/Subトピックの作成
<img width="50%" alt="IotCore2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/291adbec-91e1-0683-d072-a9cd2666bc16.png">
<img width="50%" alt="IotCore3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/a172bd43-8f51-4e9d-8aa6-8a970ee9cb36.png">


トピックIDを入力すれば、自動で適切なフォルダ内にトピックが作成されます。
<img width="50%" alt="IotCore3b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/8ee81b25-b545-206e-e073-927dc9096b75.png">

3: 「詳細設定を表示」から「プロトコル」をMQTTのみにする
<img width="30%" alt="IotCore4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/cadc506d-e535-1e1e-d518-75a4eaf23b2c.png">

<img width="50%" alt="IotCore5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/f596b00b-ce29-2fe6-7e61-3a08da5930bf.png">

4: 「作成」をクリック


### 公開鍵・秘密鍵の作成
GCPでターミナルを開いて公開鍵と秘密鍵を作成します。

```
openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem
```

<img width="80%" alt="pem.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/2df5430f-a934-220a-9ee4-ade4c4573150.png">

公開鍵・秘密鍵のデータをコピーしたい場合は、「エディタを開く」から選択すると便利です。

### デバイスの作成
「[SORACOM Beam を使用して Google IoT Core と MQTT 接続する](https://dev.soracom.io/jp/start/beam_google_iot_core/)」の「公開鍵を登録してデバイスを作成する」を参照してください。

### SORACOM側の設定
「[SORACOM Beam を使用して Google IoT Core と MQTT 接続する](https://dev.soracom.io/jp/start/beam_google_iot_core/)」の「ステップ 2: SORACOM Beam を設定する」を参照してください。

## プロジェクトID、リージョン、レジストリID、デバイスID
プロジェクトID、リージョン、レジストリID、デバイスIDの4つはMQTT接続時に入力を求められることがあります。

GCPではこれらを以下により確認できます。

プロジェクトIDはGCPでプロジェクト作成時に割り当てられたIDです。
<img width="50%" alt="projectID.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/7364c622-4678-32c0-136e-8bb00bc093d4.png">

リージョンとレジストリIDはレジストリ作成時に設定した名前と地域を使用します。
<img width="50%" alt="REGISTRY_ID.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/f5bd81ce-909d-4252-ca59-e4eca02455b2.png">

デバイスIDはデバイス作成時に設定した名前を使用します。
<img width="50%" alt="DEVICE_ID.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/66136007-b1ed-d8d6-8536-0d4f03577a94.png">

# 5. MQTT接続
## SORACOM Beamを使用する利便性
SORACOM Beamを使用する利便性は色々とありますが、私が特に便利に思ったのは、暗号化の手間が省けることです。

Google Cloud IoT Core においてMQTT接続を行うためには、TLS(Transport Layer Security)による暗号化が必要になります。
暗号化方法については、以下のMQTTサーバ認証手続きのマニュアルにあります。

[Publishing over the MQTT bridge#Downloading MQTT server certificates](https://cloud.google.com/iot/docs/how-tos/mqtt-bridge#downloading_mqtt_server_certificates)

これを見るとパスワードとしてJWT(JSON Web Token)の作成が求められます。
Googleが公開している組み込み用のサンプルプログラムを見れば、毎アクセス時にAPI関数 iotc_create_iotcore_jwt()を用いて、pemファイルやその他変数を代入し、JWTを作成しているのが分かります

- [MQTT client samples](https://cloud.google.com/iot/docs/samples/mqtt-samples)
    - [GoogleCloudPlatform
/
iot-device-sdk-embedded-c](https://github.com/GoogleCloudPlatform/iot-device-sdk-embedded-c/tree/master/examples/iot_core_mqtt_client)

PCのターミナルからATコマンド送信する場合は、上記サンプルサイトのPythonコードをPC上で走らせてJWTを生成し、コマンドに挿入するといいと思います。（実際に試していないので、できるかどうかは分かっていません）

[「GCP Cloud IoT CoreにGolangでMQTT接続する」](https://qiita.com/take_cheeze/items/2b28eff1d7f1092ea1ac)の記事を見ると、JWTの生成には以下のパラメータが必要なようです。

> - username: "unused"
- password: jwtを使って生成
  - iat: 現在時刻のUnixTime,
  - exp: 現在時刻+60分のUnixTime : 有効期限。期限を過ぎると接続が解除されるので、都度接続確認を行なう。
  - aud: projectID
  - Signin Method: SigningMethodRS256
  - SigningKey: 添付のpem

添付のpemというのは先に生成したprivate keyのことだと思います。
RAMの少ないマイコンにpemデータの領域を確保するのは、少し厄介なことです。
暗号生成の計算はマイコンの低性能CPUには負担でもあります。

そこでSORACOM Beamを使うと、以下の記事のように、この暗号化処理が省略できます。

[新機能：SORACOM が Google Cloud Platform と連携出来るようになりました！](https://blog.soracom.jp/blog/2017/06/15/soracom-google-connected/)

> - 認証情報をSIMと紐付ければSORACOMがJWTを生成・署名 → デバイス側のProvisioningを行うことなくGCPに接続可


以降は実際にEC21-JからATコマンドを送信してMQTT接続を行います。
その際には[Quectelのサイト](https://www.quectel.com/product/ec21.htm)の「Download」の「Documents」からダウンロードできるアプリケーションノート「Quectel_EC2x&EG9x&EM05_MQTT_Application_Note_V1.1」の「5.1 Example of MQTT Operation without SSL」を参照しています。

ここではSSLなしを参照している理由は、以下の図のようにSORACOMのサーバにSSLなしのMQTTで通信すれば、MQTTS通信に変換してくれるからです。

![beam_cloud-iot-core.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/dbeaf458-5cec-fa85-0acd-ea108dfa6767.png)

今回はPCのターミナルを使用していますが、マイコンに実装する時も、UART通信でATコマンドを送信するだけでいいので、とても簡単になります。

### （補足）root.pem
SORACOM Beamを使用するならば必要ないと思いますが、mqtt.googleapis.comのroot CA certification package (128 KB)は以下からダウンロードできます。

https://pki.goog/roots.pem


## PDP認証
通信試験と同様にPDP認証を行います。

```
AT+QICSGP=1,1,"soracom.io","sora","sora",0
```

```
AT+QIACT=1
```

```
AT+QIACT?
```
## AT+QMTCFG="recv/mode",\<client_idx\>,\<msg_recv_mode\>[,\<msg_len_enable\>]  

AT+QMTCFGはAT+QMTOPENを実行する前に行います。
サーバからのデータ受信設定を決めます。

msg_recv_modeを0に設定します。サーバーから受信したMQTTメッセージがURCに含まれるようになります。

msg_len_enableを1に設定します。サーバーから受信したMQTT長さメッセージがURCに含まれるようになります。

```
AT+QMTCFG="recv/mode",0,0,1 
```

## AT+QMTOPEN=\<client_idx\>,"\<host_name\>",\<port\> 
SORACOM Beamのサーバーを開きます。

client_idxは0から5のどれかの値を設定します。

SORACOM Beamのhost_nameとportは以下になります。

- host_name
    - beam.soracom.io
- port
    - 1883

```
AT+QMTOPEN=0,"beam.soracom.io",1883 
```

設定が有効になっているかを以下のコマンドで確認します。

```
AT+QMTOPEN?   
```

## AT+QMTCONN=\<client_idx\>,"\<clientID\>"[,"\<username\>"[,"\<password\>"]
SORACOM Beamのサーバーと接続します。

client_idxはAT+QMTOPENで設定したのと同じ値を使用します。

clientIDは以下になります。プロジェクトIDなどを各位の環境に合わせて設定してください。

"projects/[プロジェクトID]/locations/[リージョン]/registries/[レジストリID]/devices/[デバイスID]"

```
AT+QMTCONN=0,"projects/vigilant-router-xxxxxx/locations/us-central1/registries/test/devices/MatsuiEC21J" 
```

## AT+QMTSUB=\<client_idx\>,\<msgID \>,"\<topic1\>",\<qos1\>[,"\<topic2\>",\<qos2\>…]

クラウドからEC21-Jへデータを送信します。

データ受信時には"/devices/<デバイスID>/commands/#" というtopicへ Subscribeするように設定します。

client_idxはAT+QMTOPENで設定したのと同じ値を使用します。

msgID は1から65535のどれかの値を設定します。

qosはレベル0に設定します。 QoS0は送信成功か否かに関わらず、1回だけメッセージを発行します。
（参照「[QoSとは？MQTTにおける通信の種類！](https://sakiot.com/what-is-qos-of-mqtt/)」）

```
AT+QMTSUB=0,1,"/devices/MatsuiEC21J/commands/#",0
```

実際にデータを受信できるか確認してみます。
IoT Coreからデバイスを選択します。

<img width="50%" alt="SUB0b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/aa4cfcc9-4c8e-3234-31b4-9a4c7357d7c6.png">

「コマンドを送信」をクリックします。

<img width="50%" alt="SUB0.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/412bdca6-7623-59ae-1dda-1b29b5c863db.png">

メッセージを入力して「コマンドを送信」をクリックします。

<img width="50%" alt="SUB1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/0b7e35a4-71b9-0bcd-410b-4d0c5cf5fe2b.png">

ターミナルに受信データが表示されるのが確認できます。

<img width="80%" alt="SUB2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/0299a514-a4b3-1710-10e1-74106f2614c4.png">

## AT+QMTPUBEX=\<client_idx\>,\<msgID \>,\<qos\>,\<retain\>,"\<topic\>",\<msg_length\> 

EC21-Jからクラウドへデータを送信します。
データ送信時には/devices/<デバイスID>/events というtopicへ Publishするように設定します。

client_idxはAT+QMTOPENで設定したのと同じ値を使用します。

msgID は1から65535のどれかの値を設定します。
ただし、qos=0の場合は、0に設定しないといけません。

qosはレベル0に設定します。 

retainは0に設定します。送信に対してサーバーは応答を返しません。

msg_lengthは送信データの最大長さを設定します。


```
AT+QMTPUBEX=0,0,0,0,"/devices/MatsuiEC21J/events",10
```

最大でmsg_lengthで指定した長さのデータを送信できます。
![PUBEX1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/d62ded8c-6b1a-67cb-cdac-dc1daee9a06a.png)


もしくは以下のコマンドでもPublishできます。

```
AT+QMTPUB=0,0,0,0,"/devices/MatsuiEC21J/events"
```

データを入力後、Ctrl-Zで送信されます。
![PUB1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/5f0072f4-9176-a703-4306-b491d4ca8626.png)


## AT+QMTPUBEX=\<client_idx\>,\<msgID \>,\<topic\>/config,\<qos\>

あらかじめ設定したデータ、Configurationの読み出しが行えます。
データを読み出す場合にはsubscribeコマンドと類似した以下のコマンドを用います。


```
AT+QMTSUB=0,1,"/devices/MatsuiEC21J/config",0
```

このコマンドを実行すると、例えば以下のように設定したデータ`TestConfiguration,01234567890`が受信できます。

```Console
AT+QMTSUB=0,1,"/devices/MatsuiEC21J/config",0
OK

+QMTSUB: 0,1,0,0

+QMTRECV: 0,0,"/devices/MatsuiEC21J/config","TestConfiguration,01234567890"
```

![configuration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/ba1e1551-5460-7a02-27c5-361349f4f1c0.png)


一度データを受信すると、コマンドを再送信してもデータ受信できないのでご注意ください。
Configurationのデータに更新があるか、一度サーバと切断して、再接続すると、コマンド送信によりデータを再受信できるようになります。

GCPのConfiguration設定は、IoT Coreでデバイスの「レジストリ詳細」を開き、「構成を編集」からデータ入力画面に進むことができます

![デバイスの編集.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/1ff9949c-98ed-a56d-d58a-3cbac4b2c901.png)

## AT+QMTDISC
以下のコマンドで終了します。

```
AT+QMTDISC=0 
```


# 6.次にすること
これでMQTTに接続できていることは確認できました。本記事はここで終了とさせていただきます。
実際の応用、複数のデバイスからデータを収集し、サーバからデバイスを制御するなどは、今後試して記事にする予定です。

また、IoTは小さなデバイスに集約してこそ使い道があると思います。
今回のようにPCで制御するのではなく、EC21-Jをマイコンと接続して、UART通信で制御できるようにする予定です。
より安く、より小さく、より高機能なデバイスを作ることを目標としています。
これも実験結果を記事にする予定です。

# 参考

- [【作業メモ】GPSロガーの作成](https://qiita.com/Kosuke_Matsui/items/572fa171b6d9bd141918)
    - 本記事の続きとしてGPSロガーを作成しました。
- [SORACOM BeamによるGCPとのMQTT通信のプラットフォームバージョン「201912」対応についての覚書](https://qiita.com/Kosuke_Matsui/items/72d0606b2e0aa3516330)
    - プラットフォームバージョン「201912」対応について、MQTTバージョンを3.11 に設定する方法を解説しています
- [【作業メモ】Quectel社のLTE通信モジュールEC21の使用方法](https://qiita.com/Kosuke_Matsui/items/c25f45437078275956f3)
    - LTE通信モジュールのATコマンドやGCPの設定について解説しています。

# 追記メモ
- 2021/07/19
    - GCPでConfigurationに設定したデータを受信する方法を追加
    - [AT+QMTPUBEX=\<client_idx\>,\<msgID \>,\<topic\>/config,\<qos\>](## AT+QMTPUBEX=\<client_idx\>,\<msgID \>,\<topic\>/config,\<qos\>)