Kong Lampを作ってみた

本記事は「Kong Advent Calendar 2024」の11日目のエントリで、API GatewayのKongを体感的に使えるKong Lampを作ってみます
---
ChatGPT/OpenAI APIに代表されるように、世の中APIの必要性は増すばかり。そんなAPIを統合的に管理するKong API Gatewayの需要が高まってきています。
ここでは、APIがキックされるとRaspberry Piにつないだパトランプがピカピカ光ったり、APIの流量制限などができるKong Patrol Lampを作ります。

## この記事で学べる事
A. [Kong KonnectでのAPI管理が学べる](#i-kong-api-gatewayの立ち上げ)
B. [IoTデバイス（Raspberry Pi）上の公開APIが作れる](#iii-パトランプapiの作成)
C. [KongのPlugins、Analyticsの設定方法が分かる](#iv-パトランプapiの登録とkong-pluginsの設定)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/3b4be9e8-f0ea-1be5-4dbf-fcf79f998d16.png)

# Kong Patrol Lampの作り方はざっとこんな感じ

[ハードウェアで必要なもの](#ハードウェアで必要なもの)
1. [Kong API Gatewayの導入](#i-kong-api-gatewayの立ち上げ)
2. [Raspberry Piとパトランプをつないで光らせる](#ii-raspberry-piとパトランプをつないで光らせる)
3. [パトランプ公開APIの作成](#iii-パトランプapiの作成)
4. [KongへのAPIの登録とKong Pluginsの設定](#iv-パトランプapiの登録とkong-pluginsの設定)
5. [Kong Buttonと連動させて完成！](#v-kong-buttonと連動させて完成！)

![スクリーンショット 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)
(右側のユースケース「パトランプAPI」です)

## ハードウェアで必要なもの
| 必要なもの | 部品 |
| ---- | ---- |
| [Raspberry Pi](https://amzn.to/3OuF5Up) | [![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/5bda97e5-4a2a-95d7-b637-a79803ade07c.png)](https://amzn.to/3OuF5Up) |
| [パトランプ](https://amzn.to/3ZqMNoY) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/e6e77085-092f-10f8-2e59-9886baa9718b.png) |
| [トランジスタ](https://akizukidenshi.com/catalog/g/g111428/) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/01ff110c-fcbf-9f5c-a154-45e2f26220b0.png) |
|その他ジャンパケーブル、両面テープ、など | 適宜 |

こんなふうにKongを通して光ります。

![button_lamp2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/0b45178c-2286-520e-2bcd-427b888a4c2a.gif)


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

まだKong環境を用意していない方は、[前回記事](https://qiita.com/Ktrips/items/130f0bdbf69763a87142) と同様のこの流れに従って、KongのSAAS環境Kong Konnectで、API Gatewayを立ち上げて下さい。

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

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

### 2. Control Planeを作成
Konnectにログオンできたら、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)

これでhttps://konnect.example.com のようなURLでKong環境にアクセスできるようになりました。


## II. Raspberry Piとパトランプをつないで光らせる
ハードウェアとの連携として、Raspberry Pi（ラズパイ）とパトランプを接続して、外部からピカピカさせるAPIを作成します。

### 1. ラズパイとパトランプの接続
今回使ったパトランプは、単三電池３本の4.5Vのものでした。間にトランジスタを挟んで、５V電源のオンオフを行います。
トランジスタは平らな面を手前にして、左からE, C, Bとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/85d34392-3e31-e872-8f1d-a3516c22c705.png)

以下のようにパトランプ、トランジスタ、ラズパイを接続します。

| パトランプ側 | トランジスタ | ラズパイ側 |
| ---- | ---- | ---- |
| - | E (エミッター) | GND (白) |
| 電源 | C (コレクタ) | - |
| - | B (ベース) | GPIO 4 (緑) |
| 電源 | - | 5V (黄) |

| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/bf5b986d-bd0e-92e1-b905-269835955849.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/e2a0d490-d198-ab97-eee6-0d097e7712c8.png) |
| ---- | ---- |
| トランジスタとパトランプの接続 | 空中配線で見づらくてスミません。。 |

### 2. パトピカの確認
ラズパイの接続方法は、[このような記事](https://deviceplus.jp/raspberrypi/basic-of-raspberrypi_01/)に従って、SSHでアクセスしています。
以下のコマンドから、接続されたパトランプが動くかどうかを確認します。

```JavaScript: patrol lamp
$ gpio -g mode 4 out
$ gpio -g write 4 1
$ gpio -g write 4 0
```

まずはコマンドを打って、ラズパイからパトランプを点灯することができました。

![patlamp2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/24aa804e-0c9e-5abb-8354-9a29812393d6.gif)


## III. パトランプAPIの作成
ハードウェアとしての設定ができたので、これをAPIとして実行できるようにします。

### 1. Expressの導入
ラズパイ上のパトランプを光らせるコマンドを、外部から使えるようにAPI化します。
それにはラズパイにNode.jsとExpressを導入して、Webサーバーを立ち上げます。
以下コマンドでインストールして、Expressのバージョンが確認できたら導入が上手くいっています。

```JavaScript: Express
$ sudo apt install -y nodejs npm
$ npm install express --save
$ npm install express-generator -g
$ express --version
```

このExpressを使って、ラズパイ内にAPIを走らせるための環境を用意します。

```JavaScript: Express API
$ express iot
$ cd iot
$ npm install
$ npm start
```

これでExpress Appが立ち上がったので、ラズパイの localhost:3000 にアクセスします。
デフォルトのWelcomebページが立ち上がったら、Expressサーバーが動いています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/f017525a-4d5e-8619-2d5f-d0fd97dd3221.png)


### 2. パトランプAPIの作成

ここからパトランプAPIを作っていきます。
まずiotフォルダ下のapp.jsを開いて、以下Addedの2行を追加します。

```JavaScript: iot/app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var led = require('./routes/led'); // << *** LED API Added ***

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/led', led); // << *** LED API added ***

// ...
```

次にroutesフォルダ下にled.jsファイルを作成して、以下のようなプログラムを作ります。

```JavaScript: iot/routes/led.js
var express = require('express');
var router = express.Router();

var exec = require('child_process').exec;
exec('gpio -g mode 4 out');

router.get('/:onoff', function(req, res, next) {
  var param = {"result":"LED "+ req.params.onoff + " !", "bright":req.query.bright};
  res.header('Content-Type', 'application/json; charset=utf-8')
  res.send(param);
  if ( req.params.onoff == "on" ) {
    exec('gpio -g write 4 1');
  } else {
    exec('gpio -g write 4 0');
  }
});

module.exports = router;
```

これを実行して試してみます。

```JavaScript:LED On Off
$ curl localhost:3000/led/on
$ curl localhost:3000/led/off
```

どうでしょうか？先ほどのコマンドのようにAPIからパトランプが点灯したでしょうか？


### 3. ngrokによるトンネル化
ラズパイ上のパトランプAPIを、インターネットから使えるようなAPIにします。
それにはngrokというサービスを使用します。

https://ngrok.com にアクセスし、Sign upからユーザーを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/f4e8cc27-2d38-ac19-36de-d33af579b3aa.png)

ログオンできたら、Setup IntroductionからRaspberry Piのngrokの導入を行います。

![スクリーンショット 2024-12-02 11.57.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/fc0024cc-505f-cb11-7e6f-1b2f81a47e04.png)

画面上のステップに従って、snapでngrokをインストールします。

```JavaScript: ngrok Installation
$ snap install ngrok
$ ngrok config add-authtoken ngrok_token
$ ngrok http localhost:3000
```

自動化の設定を行なっておきます。

```python: rc.local
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

sudo -u username /usr/local/nvm/versions/node/v10.0.0/bin/node /usr/local/nvm/versions/node/v10.0.0/bin/forever start -a -d /home/pi/Programs/iot/app.js

exit 0
```



ngrokによりEndpointが生成されるので、このURL（無料枠だと一つだけ）を保存しておきます。

![スクリーンショット 2024-12-02 15.06.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/5eddbce9-af1d-bb3c-b1be-42e4c1dad7f9.png)

以下のようにEndpoint(ngrok_endpoint)とExpressサーバー(led.js)を紐付けたシェルプログラムを作っておきます。

```JavaScript: ngrok.sh
#!/bin/bash
ngrok http --domain=ngrok_endpoint localhost:3000
```

シェルプログラムをラズパイの中で自動起動させておくと、インターネット上からngrokのURLからラズパイのLED APIを起動する事ができるようになります。

![スクリーンショット 2024-12-02 15.13.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/18920759-52a8-6142-05ea-d0a1bea0467d.png)


## IV. パトランプAPIの登録とKong Pluginsの設定
作ったパトランプAPIをKong Konnect上に登録します。Kongの大事な機能、Pluginsも設定します。

### 1. パトランプAPIをサービスとして登録
Kong Konnectの左側のGateway Servicesから、New Gateway Serviceを選び、新しいサービスを作成します。
先ほどのngrok Endpointをhostに指定します。Pathは先ほど作った/led になります。

![スクリーンショット 2024-12-02 11.45.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/b8eb9963-2622-6862-913f-1945d148e22e.png)

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/86b2f0f0-4bc3-5e08-5aba-823bafbe869e.png)


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

```JavaScript:LED On Off
$ KONG=konnect.example.com
$ curl $KONG/led/on
$ curl $KONG/led/off
```
実行してみます。

![スクリーンショット 2024-12-02 14.05.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/563f0c76-fe2e-86cf-86c9-f2457518ba17.png)

Kongのプロキシを使って接続して、resultが出れば正常に接続しています。

またブラウザからも実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/c3916f91-ac7f-a299-5fcc-123edb508be2.png)

これによりパトランプが回り始めたらKongへの登録は成功です。

### 3. Kong Pluginsの設定 
KongにはPlug-inを追加するだけで様々な機能を簡単に追加する事ができます。
ここでは流量制限のRate Limit Plug-inを設定してみます。

先ほどのRouteのところからPluginsに移動します。
New Plugin画面から、"Rate Limiting Advanced"を選びます。

![スクリーンショット 2024-12-02 11.52.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/44dbc208-d530-7d49-8980-32568b18ca46.png)

Rate Limitのところで、60秒間に10回以上APIが呼ばれた429 Errorを返すように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/18f25e96-8834-c157-9bd7-4418354c5598.png)

ここで先ほどのLED APIを連続してキックしてみます。

![スクリーンショット 2024-12-02 16.39.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/34b61a79-21f2-a91d-fc2a-b47b5aa347f8.png)

そうすると、rate limit exceededのメッセージが出て一時的にAPIがコールできないようになります。
KonnectのAnalytics画面でもそれが確認できます。

![スクリーンショット 2024-12-02 16.49.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/703bfa00-b68c-1c38-fd30-536e6c3d27ab.png)


## V. Kong Buttonと連動させて完成！
前回記事で作成したKong Dash Buttonと連動させて、パトランプを光らせるようにして完成です！

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

### 1. Kong Buttonの機能追加
機能としては、長押しすると、赤く光って危険を知らせるので、それに連動してこのパトランプを光らせます。

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

そのために、[前回作った](https://qiita.com/Ktrips/items/130f0bdbf69763a87142) Buttonのスケッチに、以下のように追記します。
（Added部分の追加）

```C:M5Stick_Kong_Button.ino
#include "M5StickCPlus.h"

// ...

String led="https://konnect.x.com/led";  // *** Added ***

void http_get(String url){               // *** Added ***
  if(WiFi.status() == WL_CONNECTED){     // *** Added ***
    Serial.println("Wifi Connected");    // *** Added ***
    HTTPClient http;                     // *** Added ***
    http.begin(url);                     // *** Added ***
    int httpCode = http.GET();           // *** Added ***
        Serial.println(httpCode);        // *** Added ***
    if (httpCode == HTTP_CODE_OK) {      // *** Added ***
      String payload = http.getString(); // *** Added ***
      Serial.println(payload);           // *** Added ***
    }                                    // *** Added ***
    http.end();                          // *** Added ***
  }                                      // *** Added ***
}                                        // *** Added ***

const int longPress_ms = 1200;
void loop(){
  M5.update();

// ...

  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);
      http_get(led+"/on");               // *** Added ***
      delay(500);
    } else {
      Serial.print("GREEN");
      M5.Lcd.fillScreen(GREEN);
      M5.Lcd.printf("Home!");
      sendLine("元気だよ！ HOME！", 8522, 16581271);
      http_get(led+"/off");              // *** Added ***
      delay(500);
    }
  }
  delay(500);
}
```


### 2.全部つなげて使ってみよう！

ユースケースとしては、このボタンをお子さんなどに持っていてもらい、何かあったら長押しすると、家のパトランプが光り警告するというものです。

![スクリーンショット 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)
(一番上のユースケース、帰宅中に危険を警告、です)

ボタンを長押しすると、このようにパトランプが光だします。

![button_lamp2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/0b45178c-2286-520e-2bcd-427b888a4c2a.gif)

スマホには「問題発生！HELP！」とメッセージが届いていました！
もう一度、短く押して元気だよを送ると、パトランプは消灯します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212060/6b06e052-eca3-c934-b98a-f3eff0fa020a.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!

ヨシケン

# 参考リンク
- [Raspberry Piのセットアップ](https://deviceplus.jp/raspberrypi/basic-of-raspberrypi_01/)
- [Raspi 3](https://qiita.com/rubytomato@github/items/07c16a631cee1e9a68be)
- [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)