MATLABでもっとLINEにNotifyしたい！

これは[MATLAB/Simulink Advent Calendar 2020](https://qiita.com/advent-calendar/2020/matlab) 23日目の記事です。昨日は[@griffin921さん](https://qiita.com/griffin921)の[カバレッジってなんですか？～元ハードエンジニアから見た見解～](https://qiita.com/griffin921/items/2e4446fa2b6c332abce8)でした。

# 2020/12/28更新
スタンプの送信やちょろまかしてた箇所の修正を行いました。思ったより分量が大きくなったので、[こちら](https://qiita.com/C2_now/items/6dbaa5c2c113942dab29)の記事にまとめています。よしなに！

# これは何？
ぶっちゃけると、[これ](https://qiita.com/C2_now/items/f296e1d0fd9642727549)の焼き増しです。
フィルムカメラかな？

# 環境
MATLAB R2020a

# 今できること、やりたいこと
できること

- matlabからlineにメッセージを送る

やりたいこと

- HTTPインターフェースでやる
- スタンプの送信
- 画像の送信

# 課題
[この前作ったもの](https://qiita.com/C2_now/items/f296e1d0fd9642727549)ではLINE APIを叩くのにRESTful Webサービス関数を使っていた。ところが、Webサービスの中には「RESTful Web サービスの関数でサポートされていない機能を必要」とするものがあるようで、実際、画像の送信の糸口はつかめていなかった。

一方で、HTTPインターフェースの方には`matlab.net.http.io.ContentProvider`クラスがあり、画像やファイルの送信も手軽にできそう。前回のリベンジを兼ねて、HTTPインターフェースを用いての実装をめざした。

# HTTPインターフェースでのメッセージの送信
## とりあえずコード
```matlab
import matlab.net.http.io.*
import matlab.net.http.*
import matlab.net.*

msg = "test message from MATLAB";
token = 'hogehoge';

method = RequestMethod('POST');
header = HeaderField('Authorization', ['Bearer ', token], 'Content-Type', 'application/x-www-form-urlencoded');

msg_provider = FormProvider('message');
msg_provider.Parameters.Value = msg;

r = RequestMessage(method, header, msg_provider);
uri = URI('https://notify-api.line.me/api/notify');
resp = send(r,uri);
status = resp.StatusCode
```

## (やっぱり)申し訳程度の解説
HTTPインターフェースではHTTPメッセージの送信に`send`を用いる。その引数にメッセージと送り先(URL/URI)を渡すわけだけど、前回の`webwrite`と違ってcharやstringでベタ打ちができない。メッセージには`matlab.net.http.RequestMessage`オブジェクトを渡してあげる必要がある(URL/URIはcharやstringでもOK)。

`matlab.net.http.RequestMessage`オブジェクトは`method`(要求メソッド)、`header`(ヘッダー)、`body`(本文)などのプロパティを持つ。`method`は`matlab.net.http.RequestMethod`オブジェクトで、`header`は`matlab.net.http.HeaderField`オブジェクトで、`body`は`matlab.net.http.MessageBody`オブジェクトか`matlab.net.http.io.ContentProvider`オブジェクトで指定してやる必要がある。

要求メソッドは`POST`に指定。[LINE Notify API Document](https://notify-bot.line.me/doc/ja/)に書いてた。
ヘッダーには、認証情報と本文の`Content-Type`を指定。[LINE Notify API Document](https://notify-bot.line.me/doc/ja/)には、「Content-Typeは`application/x-www-form-urlencoded`もしくは`multipart/form-data`」とあったんだけど、前者しかうまくいかなかった。
本文は`MessageBody`オブジェクトではなく、`ContentProvider`の子クラスの`FormProvider`オブジェクトで指定。これはトライ&エラーを繰り返して見つけたんだけど、`Content-Type`が「なんちゃらform」ってなってるところから気づくべきだった。

# 画像の送信
## とりあえずコード
```matlab
import matlab.net.http.io.*
import matlab.net.http.*
import matlab.net.*

msg = "test message from MATLAB";
token = 'hogehoge';

method = RequestMethod('POST');
header = HeaderField('Authorization', ['Bearer ', token], 'Content-Type', 'multipart/form-data');

msg_provider = matlab.net.http.io.FormProvider('message');
msg_provider.Parameters.Value = msg;
img_provider = matlab.net.http.io.FileProvider('test.png');
provider = MultipartFormProvider('message', msg_provider, 'imageFile', img_provider);

r = RequestMessage(method, header, provider);
uri = 'https://notify-api.line.me/api/notify';
resp = send(r,uri);
status = resp.StatusCode
```

## (やっぱり)申し訳程度の解説
画像を送信するとき(スタンプを送るときもだけど)、注意すべきはメッセージがないと400エラーを返されて終わるということ。コマンドウィンドウにエラーが表示されるわけではないので分かりにくいったらありゃしない。そういうわけで、画像やスタンプを送るときもメッセージを送らないとダメなんだけど、`RequestMessage`オブジェクトは`body`を1つしか持てない。

というわけで、新しいクラス、`matlab.net.http.io.MultipartFormProvider`クラスの登場。このオブジェクトは複数の`ContentProvider`オブジェクトをまとめて持つことができる。こいつにメッセージを入れた`msg_provider`と画像ファイルを入れた`img_provider`を渡して、生成された`MultipartFormProvider`オブジェクトを`RequestMessage`オブジェクトに渡せばよい。

# まとめ
担当日かなりギリギリ(というか前日)に、コードの作成、記事の執筆をやってたので結構焦ってた(汗)。
けど、ちゃんと目標の画像の送信ができたのでオールオッケーです。

~~スタンプの送信をやりたいと言ってたのは見なかったことにしてください。~~今週末くらいにやります！
このコードの関数化なども今年中には…
ストックして続報を待て！