SORACOM-SIMで IoT送信してみたい - 2) モデム制御 ATコマンドを叩く

## モデム制御は ATコマンドで
前回の記事で、ATコマンドについて簡単に書きましたが、では実際に どんなATコマンドを叩けば、インターネットに接続＆データ送信できるのでしょうか。

ATコマンド仕様書だけでは、どうしていいのか？判りません。

そこで、某イベントで配付された M5Stackのプログラム(UIFlow2)を解読してみます。
これ、「M5Stac Core2 画面上のボタン押すと SIM回線接続して jsonデータを送って～」というサンプル品です。

![UIFlow2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153211/0dddee9e-9365-c595-04ff-93c302fd85f7.png)

## ATコマンド記載している部分を抽出
UIFlowのプログラムから、ATコマンドに相当する部分だけを抽出してみます。

#### ■ CAT-Mモジュールの動作を確認するコマンド群を送信する
```
AT
ATE1
ATI
AT+GSN
```

#### ■ soracomサーバに接続するコマンド群を送信する
```
AT+CFUN=0
AT+CGDCONT=1,"IP","soracom.io"
AT+CNCFG=0,1,"soracom.io"
AT+CFUN=1
AT+CGNAPN
AT+CMNB=1
AT+CPSI?
AT+CNACT=0,1
AT+CNACT?
```

#### ■ textdataに格納された文字列形式のテキストデータをsoracomサーバに送信する
```
AT+SHCONF="URL","http://uni.soracom.io"
AT+SHCONF="BODYLEN",1024
AT+SHCONF="HEADERLEN",350
AT+SHCONN
AT+SHSTATE?
AT+SHCHEAD
AT+SHAHEAD="User-Agent","CAT-M/NB-IoT GNSS Unit w/ SIM7080G"
AT+SHAHEAD="Connection","close"
AT+SHAHEAD="Accept","*/*"
AT+SHAHEAD="Content-Type","text/plain"
AT+SHBOD=★★★★
AT+SHREQ="/",3
AT+SHDISC
```
※★★★★の部分はよく判りません。

#### ■ jsondataに格納されたjson形式のテキストデータをsoracomサーバに送信する
```
AT+SHCONF="URL","http://uni.soracom.io"
AT+SHCONF="BODYLEN",1024
AT+SHCONF="HEADERLEN",350
AT+SHCONN
AT+SHSTATE?
AT+SHCHEAD
AT+SHAHEAD="User-Agent","CAT-M/NB-IoT GNSS Unit w/ SIM7080G"
AT+SHAHEAD="Connection","close"
AT+SHAHEAD="Accept","*/*"
AT+SHAHEAD="Content-Type","application/json"
AT+SHBOD=★★★★
AT+SHREQ="/",3
AT+SHDISC
```
※★★★★の部分はよく判りません。

#### 何するATコマンド群か推測できますね

ATコマンド１行１行の説明は~~しませんが~~ できませんが、これらのATコマンドを順に叩けば、モデムからインターネット接続/送信してくれそうです。

## TeraTermからATコマンド叩いてみます

### 1) モデム制御の確認
```
AT

OK
ATE1

OK
ATI

R1951.07

OK
AT+GSN

860099999999999   (*1)

OK
```
*1 : IMEIが出力されます (この例示は伏せています)

### 2) インターネット接続
```
AT+CFUN=0

+CPIN: NOT READY

OK
AT+CGDCONT=1,"IP","soracom.io"

OK
AT+CNCFG=0,1,"soracom.io"

OK
AT+CFUN=1

OK

+CPIN: READY

SMS Ready

*PSUTTZ: 25/01/02,23:04:57","+36",0
AT+CGNAPN

+CGNAPN: 1,"soracom.io"

OK
AT+CGNAPN

+CGNAPN: 1,"soracom.io"

OK
AT+CMNB=1

OK
AT+CPSI?

+CPSI: LTE CAT-M1,Online,440-10,0x40E1,87739153,262,EUTRAN-BAND19,6100,3,3,-12,-84,-58,10

OK
AT+CNACT=0,1

OK

+APP PDP: 0,ACTIVE
AT+CNACT?

+CNACT: 0,1,"10.99.99.99"     (*2)
+CNACT: 1,0,"0.0.0.0"
+CNACT: 2,0,"0.0.0.0"
+CNACT: 3,0,"0.0.0.0"

OK
```
*2 : 割当てられた グローバルIP address　(この例示は伏せています)

### 3) HTTP-POST接続
```
AT+SHCONF="URL","http://uni.soracom.io"

OK
AT+SHCONF="BODYLEN",1024

OK
AT+SHCONF="HEADERLEN",350

OK
AT+SHCONN

OK
AT+SHSTATE?

+SHSTATE: 1

OK
AT+SHCHEAD

OK
AT+SHAHEAD="User-Agent","CAT-M/NB-IoT GNSS Unit w/ SIM7080G"

OK
AT+SHAHEAD="Connection","close"

OK
AT+SHAHEAD="Accept","*/*"

OK
AT+SHAHEAD="Content-Type","text/plain"

OK
AT+SHBOD=        *3) 何も指定せずに [Enter]

ERROR
AT+SHREQ="/",3

OK

+SHREQ: "POST",201,0
AT+SHDISC

OK
```
*3 : ここに何を指定したらいいか？判らないのでエラーになりました。


## SORACOM コンソール で確認
前記のATコマンドで、SORACOMサーバ側にデータが届いていることを確認してみます。

### SIM管理

モデムから最寄りの "基地局" に繋いだか？
現在居る建物の付近に基地局があるのですね。
![SORACOM_SIM情報.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153211/7e793713-651f-c03d-cf52-f2690c69260c.jpeg)


### Harvest Data

データが SORACOMサーバに配信されたか？
とりあえず、データ送信(空っぽ)ができていることが確認できました。
![SORACOM_HarvestData1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153211/5f6e96b3-7222-8077-ada0-bac11d8322ad.png)

さて、問題は、```AT+SHBOD=``` の部分ですね。
ここが解決しないと、HTTP-POST は成り立ちませんから。

## ちゃんとATコマンドを理解しなきゃ、だわ

通信デバイス **SIM7080G** のATコマンド仕様書を入手した所に、こんな資料も見つけました。

[M5Stamp CAT-M Module の詳細情報](https://docs.m5stack.com/ja/stamp/stamp_catm) のページにある 
[SIM7070_SIM7080_SIM7090 Series_HTTP(S)_Application Note_V1.02](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/unit/sim7080g/en/SIM7070_SIM7080_SIM7090%20Series_HTTP(S)_Application%20Note_V1.02.pdf) の PDFをダウンロードしました。

この資料に HTTP-POSTする ATコマンド群の手順が例示されているではないですか。
なるほど、前記の実験したATコマンド群と ほぼ同じですね。

### 実験に使用した ATコマンド群を整理する
||ＡＴコマンド|説明|
|-:|:-|:-:|
|  1|AT    |(no operation)|
|  2|ATE   |Set Command Echo Mode|
|  3|ATI   |Display Product Identification Information|
|  4|AT+GSN|Request TA serial number identification (IMEI)|
|   | | |
|  1|AT+CFUN|Set Phone Functionality|
|  2|AT+CGDCONT|Define PDP Context|
|  3|AT+CNCFG|PDP Configure|
|  5|AT+CGNAPN|Get Network APN in CAT-M or NB-IOT|
|  6|AT+CMNB|Preferred Selection between CAT-M and NB-IoT|
|  7|AT+CPSI|Inquiring UE System Information|
|  8|AT+CNACT|APP Network Active|
|   | | |
|  1|AT+SHCONF|Set HTTP(S) Parameter|
|  2|AT+SHCONN|HTTP(S) Connection|
|  3|AT+SHSTATE|Query HTTP(S) Connection Status|
|  4|AT+SHCHEAD|Clear Head|
|  5|AT+SHAHEAD|Add Head|
|  6|**AT+SHBOD**|**Set Body**|
|  7|AT+SHREQ|Set Request Type|
|  8|AT+SHDISC|Disconnect HTTP(S)|

### よく判らない AT+SHBOD を詳しく確認
HTTP-POST/GETの BODYに関するコマンドであることは承知。
|command|request|response|
|:-|:-|:-|
|Read |AT+SHBOD?   |+SHBOD: \<body\>,\<len_body\><br><br>OK|
|Write|AT+SHBOD=\<len_body\>,\<timeout\>|OK|

|Defined Values|description|
|:-|:-|
|\<body\>|Set body value (max length is SHCONF Set value)|
|\<len_body\>|Length of \<body\>. Max value is \<bodylen\>.<br>\<len_body\>=0 Indicates that the length of the input body is calculated based on the input characters, as long as it does not exceed the maximum length|
|\<bodylen\>|Max length set by "AT+SHCONF="BODYLEN",\<bodylen\>"|
|\<timeout\>|Timeout for automatically sending edited data (100-10000 ms)|

そうか、送信するBODYの長さ(\<len_body\>)を設定してから BODYを送信する感じか。同様に 受信(HTTP-Respose)にも使うのね。

### HTTP Request Body
[SIM7070_SIM7080_SIM7090 Series_HTTP(S)_Application Note_V1.02](https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/unit/sim7080g/en/SIM7070_SIM7080_SIM7090%20Series_HTTP(S)_Application%20Note_V1.02.pdf)
に、**AT+SHBOD** の指定例が記載されていました。

```
AT+SHBOD=29,10000
> {"title":"Hello http server"}

OK
```
送信するBODY文字列 ``{"title":"Hello http server"}`` の長さ(29)を指定すると。
また上記 **AT+SHBOD** の場合、``>`` が返されれたら 続けて送信するBODY文字列をセットすると。

### HTTP Respose Read
Responseを読むのも同様なんですね。

```
AT+SHBOD=29,10000
> {"title":"Hello http server"}

OK
AT+SHREQ="/post",3　　　　<--- POST実行

OK
+SHREQ: "POST",200,457　　<---- POST成功(200)で 返信457byteあり
AT+SHREAD=0,457　　　　　　<--- 457byte読みたい
OK

+SHREAD: 457　　　　　　　<--- 457byteここから
{
"args": {},
"data": "{\"title\":\"Hello http server\"}",
　　： 略
"url": "http://httpbin.org/post"
}

AT+SHDISC
OK
```
POST実行
　``AT+SHREQ="/post",3``
したら、
　``+SHREQ: "POST",200,457``
「POST成功(200)で 返信457byteあり」 と返ってきたので
　``AT+SHREAD=0,457``
で READ(457byte)要求して結果を受信する。

 ## 再度 AT+SHBOD にチャレンジ

 ``AT+SHBOD`` に渡す情報は BODY文字列長だと判ったので、

 ### HTTP-POST接続
```
AT+SHCONF="URL","http://uni.soracom.io"

OK
AT+SHCONF="BODYLEN",1024

OK
AT+SHCONF="HEADERLEN",350

OK
AT+SHCONN

OK
AT+SHSTATE?

+SHSTATE: 1

OK
AT+SHCHEAD

OK
AT+SHAHEAD="User-Agent","CAT-M/NB-IoT GNSS Unit w/ SIM7080G"

OK
AT+SHAHEAD="Connection","close"

OK
AT+SHAHEAD="Accept","*/*"

OK
AT+SHAHEAD="Content-Type","text/plain"

OK
AT+SHBOD=27,10000　　　　　　　　<--- BODY文字列長(27)
> Hello! send from TeraTerm.　　<--- BODY文字列

OK
AT+SHREQ="/",3

OK

+SHREQ: "POST",201,0　　　　　　<--- POST成功(201), 返信0byte
AT+SHDISC

OK
```
で送信成功しました。

## SORACOM コンソール で再確認
**AT+SHBOD** の指定が成功したので、SORACOMサーバ側にデータが届いていることを確認してみます。

### Harvest Data

データが SORACOMサーバに配信されたか？
無事 TEXTデータが届いていました。(成功！)
![SORACOM_HarvestData2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153211/bc5cd890-b2a8-754b-0e41-2d27a1fc94c4.png)
<br>

以上で、本記事 [SORACOM-SIMで IoT送信してみたい - 2) モデム制御 ATコマンドを叩く](#) の記事は終了です。

---
次のページ：

　[SORACOM-SIMで IoT送信してみたい - 3) 別サーバ(GAS)に送信する](https://qiita.com/pastelxa/items/b1d2f0d5493df515d31c)

https://qiita.com/pastelxa/items/b1d2f0d5493df515d31c