ESP32からLINEメッセージとSlackメッセージを送信する

ESP32から、LINEメッセージやSlackメッセージの送信をします。
最初に、各メッセージの送信の方法を説明した後に、ESP32上のJavascript実行環境から送信する方法を示します。

# LINEメッセージ送信方法

便利なLINE Notifyを利用します。

以下、参考ページです。
　[京急線の運行情報をLINE Notifyする](https://qiita.com/poruruba/items/49956b3db54ca7689b8c)

まずは、以下をブラウザから開きます。

https://notify-bot.line.me/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/59e64789-bb6d-1c62-d863-910d4efbeb32.png)

右上のログインをクリックして、ログインします。その後、同じ右上のところから、「マイページ」を選択します。

連携中のサービスにいくつか登録されている状態ですが、最初は何も登録されていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/85a5f7a3-e45d-cbb8-aa0b-446c0415f51f.png)

「トークンを発行する」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/80faf02a-b037-bff4-905d-efdcccebcb63.png)

トークン名には適当な名前を入力します。今回は「QuickJS_ESP32」とします。
送信するトークルームには、送りたい先のグループを選択します。
最後に発行すると、トークンが発行されます。後で使いますので覚えておきます。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/f6a724e5-98ca-6741-025f-49ecd005f7da.png)

あとは、このトークンとともにHTTP Postで呼び出せば、相手のグループにメッセージが送られ、結果としてJSONが返ってきます。
Node.jsで送る場合の例を以下に示します。
(node-fetchは、v2.6.7を使います。)
引数messageに送信したいメッセージを、引数tokenに先ほど生成したトークンを指定します。

```js
const fetch = require('node-fetch');
const { URL, URLSearchParams } = require('url');
const Headers = fetch.Headers;

function line_notify(message, token){
  var params = {
      message: message
  };
  return do_post_urlencoded_token('https://notify-api.line.me/api/notify', params, token);
}

function do_post_urlencoded_token(url, params, token) {
  const headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization' : 'Bearer ' + token });
  var body = new URLSearchParams(params);

  return fetch(url, {
      method: 'POST',
      body: body,
      headers: headers
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    })
}
```

# Slackメッセージ送信方法

以下参考ページです。
　[今更ながらSlackBotを作ってみた：Incoming Webhooks](https://qiita.com/poruruba/items/b78fb83ae969e9e03b75)

SlackのApps管理画面にログインします。

https://api.slack.com/apps

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/4fbdbc04-874e-aee6-8ae4-3d31c4e7b619.png)

「Create New App」ボタンを押下します。ダイアログが表示されますので、「From scratch」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/7237d4b6-2d4d-8dbf-a87c-153e0bd9e287.png)

App Nameに適当名前を入力します。例えば、「QuickJS_ESP32」と入力します。
Pick a workspace to develop your app in: には、メッセージを送りたいワークスペースを選択します。
最後に、「Create App」ボタンを押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/fc59d859-cdc5-a607-e859-efc516c96320.png)

Appの管理画面が表示されます。
Incomming WebHooksをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/7204f1b9-5182-e3e2-0862-1a1fcda159ea.png)

以下のOn/OffスイッチをOnにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/bd01497a-3642-bd9c-a040-dcef821df70f.png)

「Add New Webhook to Workspace」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/06f0f68f-0da3-6f93-1e15-7953d6d26f44.png)

そうすると、選択したワークスペースのどのチャネルにメッセージを送信するかの選択画面が表示されます。今回は、#generalを選択しました。
最後に「許可する」ボタンを押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/1dcbec81-8750-568a-6879-c7e961096eda.png)

そうすると、「Webhook URL」に項目が増えているのがわかります。URLをメモっておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/03610fde-331a-fd5f-5708-1e597511644c.png)

あとは、このURLに対して送信したいメッセージを送るだけです。
Node.jsで送信する場合の例を示します。
(node-fetchは、v2.6.7を使います。)
引数messageに送信したいメッセージを、引数urlに先ほど生成したWebhook URLを指定します。

```js
const fetch = require('node-fetch');
const Headers = fetch.Headers;

function slack_notify(message, url){
  var params = {
      text: message
  };
  return do_post(url, params);
}

function do_post(url, body) {
  const headers = new Headers({ "Content-Type": "application/json" });

  return fetch(url, {
      method: 'POST',
      body: JSON.stringify(body),
      headers: headers
    })
    .then((response) => {
      if (!response.ok)
        throw 'status is not 200';
      return response.json();
    });
}
```

# ESP32のJavascript実行環境で送信

動作環境としては、以下のESP32用のJavascript実行環境のファームウェアを使います。

電子書籍：M5StackとJavascriptではじめるIoTデバイス制御

https://poruruba.booth.pm/items/3735175

このJavascript実行環境では、メモリ使用量の関係で、HTTP通信しかできません。
そこで、外部にHTTPS通信に変換する中継サーバを設置して送信します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/3465e785-64ce-e985-98cf-746ac371b7b0.png)

中継サーバは、Node.jsで作成しました。
あらかじめ、Node.js v12以降がインストールされている必要があります。

以下のGitHubに上げておきました。

poruruba/HttpGateway

https://github.com/poruruba/HttpGateway

ZIPダウンロードして以下のようにセットアップします。

```
> unzip HttpGateway-master.zip
> cd HttpGateway-master
> npm install
```

あとは、Node.jsで実行するだけですが、もし中継サーバのポート番号を変えたい場合は、.envファイルを作成して、以下のように記載します。以下は、ポート番号40080の場合です。

```.env
PORT=40080
```

実行は以下のようにします。

```
> node app.js
```

中継サーバの実体は「api/controllers/httpgateway/index.js」にありますが、特に変更は不要です。

あとは、以下のようなJavascriptをESP32で実行すればよいです。
Httpモジュールを使います。

```js:main.js
import * as http from "Http";

http.setGatewayServer('http://[立ち上げたNode.jsサーバのホスト名]:40080/httpgateway-call');

const slack_url = '[SlackのWebhook URL]';
const line_token = '[LINEのトークン]';

var method_type = http.content_urlencode | http.method_post | http.resp_json;
var params = {
	message: "Hello World"
};
var headers = {
	Authorization: 'Bearer ' + line_token
};
var result = http.fetch(method_type, 'https://notify-api.line.me/api/notify', params, headers);
console.log(JSON.stringify(result));
console.log('end');

var message = {
	text: "Hello World"
};
var result = http.postText(slack_url, message);
console.log(JSON.stringify(result));
console.log('end');
```

少し解説します。

```http.setGatewayServer()```は、中継サーバのURLを設定するためのものです。一度実行すれば、不揮発に記憶するため、この行の実行は1回だけよいです。

まずは、LINEメッセージ送信の部分です。
Content-Typeがちょっと特殊で、```http.fetch()```にて、```application/x-www-form-urlencoded``` の形式で送信しています。LINEのトークンはHTTP ヘッダに指定しています。Body部に送信したいメッセージを指定します。

次は、Slackメッセージ送信部分です。
一般的な、HTTP PostのJson形式での送信であるため、```http.postText()```を使っています。必要なシークレットは、URLに含まれていますので、Body部に送信したいメッセージを指定するだけです。

以上