Kong Buttonを作ってみた

本記事は「Kong Advent Calendar 2024」の9日目のエントリで、API GatewayのKongを体感的に使えるKong Buttonを作ってみます
---
ChatGPT/OpenAI APIに代表されるように、世の中APIの必要性は増すばかり。そんなAPIを統合的に管理するKong API Gatewayの需要が高まってきています。
ここでは、ボタンを押すとKong API Gateway上の様々なAPIに接続し、APIを効率的に管理する仕組みを作ります。

まずはシンプルに、ボタンを押すとKong Gateway上のLINE Messaging APIにつながり、「家に帰るよ」メッセージを送る、Kong Dash Buttonを作ります。

## この記事で学べる事
A. [Kong API Gatewayの設定方法を理解する](#i-kong-api-gatewayの立ち上げ)
B. [メッセージAPI（LINE Notify）の使い方が学べる](#iii-line-notifyの設定)
C. [IoTデバイス（Arduino/M5Stack）でAPIが使えようになる](#iv-line-notifyをkongにセットアップ)

フリスクサイズのボタンを押すことにより、様々なAPIをキックして、便利に使えるデバイスを作ります。

![スクリーンショット 2024-08-13 17.42.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/db4ee561-25c4-ee64-7821-05aece0985bd.png)

# Kong Dash Buttonの作り方はざっとこんな感じ

[ハードウェアで必要なもの](#ハードウェアで必要なもの)
1. [Kong API Gatewayの立ち上げ](#i-kong-api-gatewayの立ち上げ)
2. [最初のAPI httpbinに接続](#ii-最初のapi-httpbinに接続)
3. [LINE Notifyの設定](#iii-line-notifyの設定)
4. [Kong上にLINE Notifyをセットアップ](#iv-line-notifyをkongにセットアップ)
5. [M5Stickでボタンを作って組み合わせて完成！](#v-m5stickでボタンを作って完成)

![スクリーンショット 2024-08-13 18.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/45bcabc6-ee1f-97b9-01df-79e7dfc62ae8.png)
(一番上のユースケース、お家に帰るよボタン、を作ります)

## ハードウェアで必要なもの
以下のようなデバイス、部品をそろえてKong Dash Buttonを作っていきます。
| 必要なもの | 部品 |
| ---- | ---- |
| [M5Stick Plus](https://amzn.to/4fMEGsD) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/be321c17-b3dc-822a-55b0-0043875a3cd2.png) |
| フリスクの箱 | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/05e55540-29b5-e5f3-e496-39ab01f5184d.png) |
|その他両面テープ、セロテープなど | 適宜 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/2eb658a9-4482-ceff-d52c-c2e2719ede2d.png)

## I. Kong API Gatewayの立ち上げ

まずKong環境を用意するために、KongのSAAS環境Konnectで、API Gatewayを立ち上げます。

### 1. [Kong Konnect](https://cloud.konghq.com) にアクセス
https://cloud.konghq.com にアクセスして、ユーザー、パスワードなどを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/e1ff997b-017e-080c-465d-413cd6fe2217.png)

### 2. Control Planeを作成
Gateway Managerスクリーンから New Control Plane を押して、新しいGatewayを作ります。
![スクリーンショット 2024-07-13 16.37.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/0432aff9-ba3f-01d8-f685-22f3f5761a61.png)

### 3. Data Planeを作成
Data Plane Nodesには、Kongのフルマネージド環境の Dedicated Cloud Instances を選びます。
![スクリーンショット 2024-07-13 16.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/79e0b87a-4e69-6059-0e44-be07bc251d4f.png)

そうすると Payment method の設定を求められるので、クレジットカードの支払い方法をセットします。
（無料枠＄500があるので、その範囲内の最小限の使い方なら課金されることはありません）

![スクリーンショット 2024-07-13 16.38.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/3b1e6295-66fd-b97e-3ff2-e1eb63741315.png)

Regionを選ぶ画面が出るので、USなどの適当なRegionを選びます。

![スクリーンショット 2024-07-13 16.58.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/5906abda-7e97-10e8-5ead-9de52db019b7.png)

### 4. (Option) ドメインの設定
（オプションですが）左側メニューのCustom Domainsから、個人のドメイン名を紐づけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/9a0d42d0-4c93-dc1c-c6a2-44bc98ac3851.png)


## II. 最初のAPI httpbinに接続
Kong Konnectがセットアップできたら、そこに最初のAPIを登録します。

### 1. サービスの作成
Kong Konnectの左側のGateway Servicesから、New Gateway Serviceを選び、新しいサービスを作成します。
ここではテストのため、以下のような http://httpbin.org というAPIを登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/2b0bbfb8-7b39-9aeb-720b-35b5ad54d348.png)

### 2. ルートの作成
次にこのサービスのルートを以下のように作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/43898b76-c290-7a03-78d8-5328eb7b5d29.png)

### 3. httpbinをテスト
設定が済んだらコマンドラインからcurlで接続を確認します。
KONGプロキシに設定しているアドレスは、ご自分の独自ドメインかこのKonnectのURLをセットします。

```Curl:httpbin
$ KONG=konnect.example.com
$ curl $KONG/httpbin/ip
```
実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/ffabe42b-5c10-b024-465b-b34ad9d55b4e.png)

画面のようにIPアドレスが表示されたら、正常にサービス/ルートがKong Konnectに登録されている事が分かります。

## III. LINE Notifyの設定
それでは次にLINEにメッセージを送るLINE Notify APIを設定していきます。

### 1. [line-notify](https://notify-bot.line.me/) にアクセス
https://notify-bot.line.me/ にアクセスし、LINE Developerアカウントを作成します。右上のログインからユーザ、パスワードを作成し、ログインします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/51b614b3-c045-2e23-19f7-db8f3f2fb413.png)

* 残念ながらLINEではこのNotifyは2025/3/31でサービス終了になるようです。それ以後は別のNotificationサービスを登録し直す必要があります。
(LINE Developer) "2016年9月から開発者の皆様に提供してまいりましたLINE Notifyですが、より良いサービスを提供するため、経営資源を後継の類似プロダクトに集中させることとなり、2025年3月31日にサービスを終了させていただくことになりました。"

### 2. トークンを取得
右上の「マイページ」メニューから、一番下のアクセストークンの発行に行き、「トークンを発行する」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/5af7650a-dc90-72d2-f35a-0c1f691a21b5.png)

トークン名を入力し、「1:1でLINE Notifyから通知を受け取る」を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/e31b32cf-00bf-aa3d-eecb-a1589d576d07.png)

この後に表示されるLINEトークンをコピーしておきます。

このセットアップで連携中のサービスとして登録されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/8b556be7-e5f8-9267-a6e2-8a13ffd645cd.png)

### 3. LINE Notify接続を確かめる
コマンドラインからLINE Notifyでメッセージが送れるか試してみます。XXXXには前の項で取得したトークンをセットします。
```Curl:LINE Notify
$ curl -X POST -H "Authorization: Bearer XXXX" -F "message=ただいま！" https://notify-api.line.me/api/notify
```
これを実行してstatusが200で返ってきたら、メッセージ送信が成功しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/c3708ad0-799b-7548-91c8-61a96dbc87e2.png)

スマホのLINEを見てみると、このようにメッセージが来ています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/4077b972-b96d-82aa-d05a-3b134ec866a8.png)


# IV. LINE NotifyをKongにセットアップ
LINE Notifyが動くことを確認できたら、このAPIをKongにセットアップします。

### 1. Kong Konnectにセット
再度[Kong Konnect](https://cloud.konghq.com)に行き、New Gateway Serviceの登録を行います。
以下のようにLINE Notifyをサービスとして設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/9e1fa4f1-d322-a11b-b100-7c3f97f00788.png)

サービスに続いて、ルートを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/896bde65-4641-744e-908b-188110261124.png)

### 2. Kongからの接続をテスト
先ほど設定したKONG経由のプロキシを使って、KongにつながっているLINE Notifyをキックしてみます。
```Curl:Kong Notify
$ KONG=konnect.example.com
$ curl -X POST -H "Authorization: Bearer XXXX" -F "message=コング ただいま！" $KONG/line/api/notify
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/fa2c1d48-ae60-0f73-bc35-5ba6c0d76202.png)

LINE側、Kong側双方のセットアップができていると、ちゃんとKong経由でメッセージが届きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/9b0f9e11-bb43-cc58-5744-bb9c9e61cd53.png)


これでKong経由でLINE Notifyが送れるようになりました。KonnectのAnalyticsでも接続が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/f5d13733-2c6f-9987-8eb9-daaa1b693791.png)


## V. M5Stickでボタンを作って完成
LINE、Kongの設定ができたので、物理的なボタンを押すことにこのAPIを発火できるようにします。Arduino互換機で小さなボタンが付いた[M5StickC Plus](https://amzn.to/4fMEGsD)を使います。

### 1. M5Stickのセットアップ
M5Stack/M5Stickのプログラミングをするために、Arduino IDEのセットアップを行います。Arduino IDEの導入は、[こちらのエントリ](https://deviceplus.jp/mc-general/smart-clothespin-with-m5stack-01/) などにまとまっていますので、参照してやってみて下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/12605b46-3bfe-6cc8-1867-b8e4da07f8e3.png)


### 2. スケッチを書く
M5Stickとパソコンがつなげたら、M5Stickの前面ボタンを押したら、APIが起動するようなプログラム/スケッチを描きます。
こちらはサンプルのスケッチです。AAAAはWifiのSSID、BBBBはそのパスワード、XXXXはLINEのトークンです。lineHostのところにある"KONG"はご自分のdomainを設定してみて下さい。

```Arduino:M5Stick_Kong_Button.ino
#include "M5StickCPlus.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid     = "AAAA";
const char* password = "BBBB";

//const char* lineHost = "notify-api.line.me";
const char* lineHost = "KONG";
const char* lineUrl = "/line/api/notify";
const char* lineToken= "XXXX";

void sendLine(String message, int PSI=0, int SI=0) {
  WiFiClientSecure client;
  Serial.println("Try");
  client.setInsecure();
  if (!client.connect(lineHost, 443)) {
    Serial.println("Connection failed");
    return;
  }
  Serial.print("Line Connected");
  String query = String("message=") + message;
  if(SI >0){
   query = query + "&stickerPackageId="+PSI + "&stickerId="+SI;
  }
  Serial.println(query);
  String request = String("") +
                   "POST " + lineUrl + " HTTP/1.1\r\n" +
                   "Host: "+ lineHost + "\r\n" +
                   "Authorization: Bearer " + lineToken + "\r\n" +
                   "Content-Length: " + String(query.length()) +  "\r\n" +
                   "Content-Type: application/x-www-form-urlencoded\r\n\r\n" +
                   query + "\r\n";
  client.print(request);

  while (client.connected()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
    if (line == "\r") {
      break;
    }
  }
 
  String line = client.readStringUntil('\n');
  Serial.println(line);
}
 
void setup() {
  Serial.begin (9600);
  M5.begin();  
  M5.Lcd.setRotation(3);
  M5.Lcd.setTextSize(2);

  Serial.printf("Connecting to %s\n", ssid);
  M5.Lcd.printf("Connecting to %s\n", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    M5.Lcd.print(".");
  }
  Serial.printf("\nWiFi connected\n");
  M5.Lcd.printf("\nWiFi connected\n");

}

const int longPress_ms = 1200;
void loop(){
  M5.update();
  Serial.print(".");
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(6);
  M5.Lcd.setCursor(10, 10);
  M5.Lcd.setTextColor(WHITE); // (WHITE, BLACK, RED, GREEN, BLUE, YELLOW...)
  M5.Lcd.printf("Kong");
  M5.Lcd.setCursor(10, 50);
  if (M5.BtnA.wasPressed()) {
    delay(longPress_ms);
    if(M5.BtnA.read() == true){ 
      Serial.print("Red");
      M5.Lcd.fillScreen(RED);
      M5.Lcd.printf("Help!");
      sendLine("問題発生！ HELP！", 8522, 16581287);
      delay(500);
    } else {
      Serial.print("GREEN");
      M5.Lcd.fillScreen(GREEN);
      M5.Lcd.printf("Home!");
      sendLine("元気だよ！ HOME！", 8522, 16581271);
      delay(500);
    }
  }
  delay(500);
}
```

### 3. スケッチを流し込み動かしてみる
それでは上記スケッチをM5Stickに流し込み、ボタンを押してみます。
ボタンはフリスクケースの上から押しても反応するように、少し厚みを持たせています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/d3c2333d-7000-4e4b-3fef-9dd82b88fece.png)

フリスクのフタを閉めるとこのようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/20ac6705-cb8d-426c-6c65-2fb563a6130e.png)


ユースケースとしては、このボタンをお子さんなどに持っていてもらい、何かあったら押すと安否が確認できるというものです。
![スクリーンショット 2024-08-13 18.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/45bcabc6-ee1f-97b9-01df-79e7dfc62ae8.png)
(一番上のユースケース、お家に帰るよボタン、です)


まず電源を入れて、Wifiに接続できると、Kongという文字が出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/511a1943-b136-a721-d206-4c2de663169a.png)

ボタンを一回押すと、家に帰ったということで、「元気だよ！」とスタンプと共に送られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/f9903ded-e691-7002-4c9a-e5e34efbb027.png)

長押しすると、赤く光って危険を知らせます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/dfaef120-15ff-bf4f-ba8f-3a293dc11946.png)

スマホにはこのようにスタンプと共にメッセージが届いていました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/6b06e052-eca3-c934-b98a-f3eff0fa020a.png)

見事、ハードウェアからKong、そしてAPIへと連携ができています。
もちろんこのアクセス状況などはKong Manager上で確認する事ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/b2024e1a-6cd6-7267-08a8-d77324251b9c.png)

# まとめ

という事で、Kong Konnect上にAPIをセットし、それをハードウェアのボタンから起動することができました。
Kongを使うとさまざまなAPIをまとめて管理でき、またCloud Gatewayを使うと自身で環境を持たなくてもフルマネージドな環境が手に入ります。
今後もさまざまなAPIを追加して、便利な環境にしていこうと思います！

![スクリーンショット 2024-08-13 17.42.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/db4ee561-25c4-ee64-7821-05aece0985bd.png)

それでは、よいKongを！ Happy Kong!

ヨシケン

## 参考リンク
- [M5Stackのセットアップ](https://deviceplus.jp/mc-general/smart-clothespin-with-m5stack-01/)
- [Kongのセットアップ](https://qiita.com/rubytomato@github/items/07c16a631cee1e9a68be)
- [Kongのドキュメント(英語)](https://github.com/alexa-pi/AlexaPi/wiki/Installation)
- [Kong Konnectのページ(英語)](https://developer.amazon.com)
- [Blog.ktrips.netヨシケンのモノ作りブログ](http://blog.ktrips.net)