11
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LINEボットを立ち上げるまで。LINEビーコンも。

Last updated at Posted at 2020-12-13

Node.jsでLINEボット用のユーティリティクラスを作成したので、立ち上げるまでをまとめておきます。(時間がたつと忘れてしまうので)
ついでに、ESP32でLINEビーコンを作成し、LINEボットで連携します。

(とは言っても、今まで複数投稿してきた内容をまとめただけです。ベースとなった投稿は、本投稿の最後に示しておきました。)

以下のAWS Lambdaエミュレーション環境をベースにします。

poruruba/amplify_template
 https://github.com/poruruba/amplify_template

先に順番を示しておきます。

・LINEチャネルの作成
・Node.jsサーバ立ち上げ
・Node.jsサーバにエンドポイントの作成
・LINEボットWebhook設定
・友達登録
・メッセージ応答のカスタマイズ
・(必要に応じて)ESP32でLINEビーコンを作成

LINEチャネルの作成

LINEデベロッパーコンソールから登録します。

LINEデベロッパーコンソール
https://developers.line.biz/console/

プロバイダを選択または新規作成したのち、チャネル設定の新規チャネルを選択します。

image.png

チャネルの種類は、Messaging APIです。

image.png

適当に入力し、利用規約に同意して、「作成」ボタンを押下します。

image.png

作成後に表示されるチャネル基本設定にあるチャネルシークレットとMessaging API設定にあるチャネルアクセストークン(長期)の発行ボタンで生成されるチャネルアクセストークン(長期)を覚えておきます。

また、Messaging API設定の応答メッセージは無効に変更しておきます。グループ・複数人チャットへの参加を許可するも有効にしておきます。

Node.jsサーバ立ち上げ

前提
 Node.jsがインストールされていること

以下から、ZIPダウンロードします。

poruruba/express_template
 https://github.com/poruruba/express_template

以下の通りに展開し、セットアップします。

> unzip express_template-master.zip
> cd express_template-master
> mkdir cert
> touch .env
> npm install
> node app.js

HTTPSである必要があるため、上記の途中でcertにSSL証明書を格納します。ファイル名は、app.jpを参照してください。
特に何もしなければ、HTTPSがポート10443で立ち上がるかと思います。

Node.jsサーバにエンドポイントの作成

LINEボット用のフォルダを作成します。

> mkdir api\controllers\linebot

上記フォルダに以下の2つのファイルを作成します。
・index.js
・swagger.yaml

LINEボットとして応答できるようにするためには、最低限以下の記載があればよいです。

api/controllers/linebot/index.js
'use strict';

const config = {
  channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN || '【LINEチャネルアクセストークン(長期)】',
  channelSecret: process.env.LINE_CHANNEL_SECRET || '【LINEチャネルシークレット】',
};

const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/';
const LineUtils = require(HELPER_BASE + 'line-utils');
const line = require('@line/bot-sdk');
const app = new LineUtils(line, config);

app.message(async (event, client) =>{
  console.log(event);

  var message = { type: 'text', text: event.message.text + ' ですね' };
  return client.replyMessage(event.replyToken, message);
});

exports.fulfillment = app.lambda();

【LINEチャネルアクセストークン(長期)】と【LINEチャネルシークレット】のところに、先ほど覚えておいた値を付記しておきます。
LINEアプリからチャットメッセージを入力すると、 app.message()が呼び出されます。
event.message.textに、受信したチャットメッセージがありますので、とりあえず、単純に、チャットでエコーバックするようにしておきました。

api/controllers/linebot/swagger.yaml
swagger: '2.0'
info:
  version: 'first version'
  title: Lambda Laboratory Server
  
paths:
  /linebot:
    post:
      x-handler: fulfillment
      parameters:
        - in: body
          name: body
          schema:
            $ref: "#/definitions/CommonRequest"
      responses:
        200:
          description: Success
          schema:
            $ref: "#/definitions/CommonResponse"

Node.jsサーバを再起動します。

> node app.js

細かな処理は、api/helpers/line-utils.js で処理させています。以下のnpmモジュールを使っています。

line/line-bot-sdk-nodejs
 https://github.com/line/line-bot-sdk-nodejs

LINEボットのWebhook設定

LINEデベロッパーのMessaging API設定に、Webhook設定があります。
ここに、立ち上げたNode.jsサーバのURLを指定します。以下のような感じです。

 https://【Node.jsサーバのホスト名】:10443/linebot

これで、Webhookの利用をOKにして、検証ボタンを押下すると、「成功」と表示されるかと思います。

友達登録

Messaging API設定のQRコードに表示されているQRコードから、ご自身のLINEアプリでこのLINEボットを友達として登録しておきましょう。
チャットしてみましょう。エコーバックされてくるかと思います。

image.png

※タイトルがちょっと違いますが気にしないでください。。。

メッセージ応答のカスタマイズ

応答できるメッセージオブジェトの種類は以下に定義されています。

メッセージオブジェクト
 https://developers.line.biz/ja/reference/messaging-api/#message-objects

・テキストメッセージ
・スタンプメッセージ
・画像メッセージ
・動画メッセージ
・音声メッセージ
・位置情報メッセージ
・イメージマップメッセージ
・テンプレートメッセージ
・Flex Message

このうち、テンプレートメッセージとFlex Message以外は名前の示す通りの単機能のメッセージなのですが、テンプレートメッセージとFlex Messageは単機能を組み合わせて定義済みのテンプレートだったり、自由に定義可能なレイアウトのメッセージです。

今回は、上記を組み合わせて、定型レイアウトを作っておきました。

・SimpleResponse
・BasicCard
・List
・Carousel
・QuickReply

以下に利用する際のソースコードを示しておきます。

api/controllers/linebot/index.js
'use strict';

const config = {
  channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN || '【LINEチャネルアクセストークン(長期)】',
  channelSecret: process.env.LINE_CHANNEL_SECRET || '【LINEチャネルシークレット】',
};

const HELPER_BASE = process.env.HELPER_BASE || '../../helpers/';

const line = require('@line/bot-sdk');
const LineUtils = require(HELPER_BASE + 'line-utils');
const app = new LineUtils(line, config);

app.message(async (event, client) =>{
  console.log(event);

	if( event.message.text == '/' ){
		var message = app.createSimpleResponse(event.message.text);
		var list = [
			{
				title: "SimpleResponse",
				action: {
					type: "postback",
					data: "SimpleResponse"
				}
			},
			{
				title: "BasicCard",
				action: {
					type: "postback",
					data: "BasicCard"
				}
			},
			{
				title: "List",
				action: {
					type: "postback",
					data: "List"
				}
			},
			{
				title: "Carousel",
				action: {
					type: "postback",
					data: "Carousel"
				}
			},
		];
		var quickReply = app.createQuickReply(list);
		message.quickReply = quickReply;

		return client.replyMessage(event.replyToken, message);
	}else{
		var message = app.createSimpleResponse(event.message.text + ' ですね');
		return client.replyMessage(event.replyToken, message);
	}
});

app.postback(async (event, client) =>{
	console.log(event);

	if(event.postback.data == 'SimpleResponse' ){
		var message = app.createSimpleResponse('SimpleResponseです');
		return client.replyMessage(event.replyToken, message);
	}else
	if(event.postback.data == 'BasicCard' ){
		var message = app.createBasicCard("BasicCard", "linebot sample", "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_1_cafe.png", 
																			"BasicCardです", "ボタンテキスト", "ボタンを押下");
		return client.replyMessage(event.replyToken, message);
	}else
	if(event.postback.data == 'List' ){
		var list = [
			{
				title: "Brown Cafe",
				desc: "Brown Cafeです",
				image_url: "https://scdn.line-apps.com/n/channel_devcenter/img/flexsnapshot/clip/clip10.jpg",
				action_text: "選択",
				action: {
					type: "message",
					text: "Brown Cafeを選択"
				}
			},
			{
				title: "Brow&Cony's Restaurant",
				desc: "Brow&Cony's Restaurantです",
				image_url: "https://scdn.line-apps.com/n/channel_devcenter/img/flexsnapshot/clip/clip11.jpg",
				action_text: "選択",
				action: {
					type: "message",
					text: "Brow&Cony's Restaurantを選択"
				}
			},
			{
				title: "Tata",
				desc: "Tataです",
				image_url: "https://scdn.line-apps.com/n/channel_devcenter/img/flexsnapshot/clip/clip12.jpg",
				action_text: "選択",
				action: {
					type: "message",
					text: "Tataが選択されました"
				}
			},
		];
		var message = app.createList("List", list);
		return client.replyMessage(event.replyToken, message);
	}else
	if(event.postback.data == 'Carousel' ){
		var list = [
			{
				title: "Brown Cafe",
				desc: "Brown Cafeです",
				image_url: "https://scdn.line-apps.com/n/channel_devcenter/img/flexsnapshot/clip/clip10.jpg",
				action_text: "選択",
				action: {
					type: "message",
					text: "Brown Cafeを選択"
				}
			},
			{
				title: "Brow&Cony's Restaurant",
				desc: "Brow&Cony's Restaurantです",
				image_url: "https://scdn.line-apps.com/n/channel_devcenter/img/flexsnapshot/clip/clip11.jpg",
				action_text: "選択",
				action: {
					type: "message",
					text: "Brow&Cony's Restaurantを選択"
				}
			},
			{
				title: "Tata",
				desc: "Tataです",
				image_url: "https://scdn.line-apps.com/n/channel_devcenter/img/flexsnapshot/clip/clip12.jpg",
				action_text: "選択",
				action: {
					type: "message",
					text: "Tataが選択されました"
				}
			},
		];
		var message = app.createCarousel('Carousel', list);
		return client.replyMessage(event.replyToken, message);
	}

});

exports.fulfillment = app.lambda();

チャットメッセージで「/」(スラッシュ)を送ると、定型レイアウト名のクイックリプライが表示され、選択するとpostbackが返り、それに応じた定型レイアウトを表示する、というものです。

app.postback() の部分がポストバックを受け取る部分です。

簡単に補足すると、以下の関数で、定型メッセージを作成し、

・SimpleResponse:app.createSimpleResponse()
・BasicCard:app.createBasicCard()
・List:app.createList()
・Carousel:app.createCarousel()

出来上がったmessageを、以下のように渡します。

return client.replyMessage(event.replyToken, message);

クイックリプライを追加する場合には、以下の関数でQuickReplyを作成し

・QuickReply:app.createQuickReply()

出来上がったquickReplyを前述のmessageに追加します。送信方法は同じです。

message.quickReply = quickReply;

SimpleResponseの例です。

image.png

BasicCardの例です。

image.png

Listの例です。

image.png

Carouselの例です。

image.png

上記は、LINEアプリからのチャットの応答としてメッセージを返信しました。一方でこちらの好きなタイミングでメッセージを送りたい場合は、replyMessageではなくpushMessageを使います。送信の際には、messageに加えて、送信先を示すLINEユーザIDが必要です。

return app.client.pushMessage('【LINEユーザID】', message);

今回は、いくつかの定型メッセージを作成しましたが、他にもLINEメッセージの仕様を参考にしたり、以下のツールを利用すれば、簡単に作成できるかと思います。

Flex Message Simulator:Flex Messageを視覚的に確認しながらメッセージを作れます。
 https://developers.line.biz/flex-simulator/

LINE Bot Designer:単純なパラメータの指定でメッセージを作成できます。
 https://developers.line.biz/ja/services/bot-designer/

メッセージオブジェクト:LINEの仕様です。
 https://developers.line.biz/ja/reference/messaging-api/#message-objects

ESP32でLINEビーコンを作成

次は、ESP32でLINEビーコンを作成します。

まず以下のページから、LINE Simple BeaconのハードウェアIDを発行します。

LINE Official Account Manager:LINE Beacon
 https://manager.line.biz/beacon/register

image.png

アカウントリストの中に、先ほど作成したMessaging APIのチャネルがあるかと思います。
それを選択し、その次の画面で表示される「ハードウェアIDを発行」ボタンを押下します。
そすると、16進数5桁のハードウェアIDが払い出されます。

image.png

Arduino IDEまたはPlatformIOのESP32のソースコードを以下に示します。

LineBot.ino
#include <M5StickC.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

const uint8_t LINE_BEACON_HWID[] = { 0x01, 0x02, 0x03, 0x04, 0x05 }; // LINE BEACON HWID
const uint8_t LINE_BEACON_DEVICE_MESSAGE[] = { 'h', 'e', 'l', 'l', 'o' }; // LINE BEACON DEVICE MESSAGE(1-13)

#define UUID_SERVICE_SHORT  0xFE6F
#define UUID_SERVICE BLEUUID((uint16_t)UUID_SERVICE_SHORT)

BLEAdvertising *pAdvertising;

void taskServer(void*) {
  BLEDevice::init("M5StickC");

  BLEServer *pServer = BLEDevice::createServer();

  BLEService *pService = pServer->createService(UUID_SERVICE);

  pService->start();

  pAdvertising = pServer->getAdvertising();
  pAdvertising->addServiceUUID(UUID_SERVICE);
  BLEAdvertisementData advertisementData = BLEAdvertisementData();
  advertisementData.setFlags(0x06);

  std::string strServiceData = "";

  strServiceData += (char)0x03;
  strServiceData += (char)0x03;
  strServiceData += (char)0x6f;
  strServiceData += (char)0xfe;

  strServiceData += (char)(10 + sizeof(LINE_BEACON_DEVICE_MESSAGE));
  strServiceData += (char)0x16;
  strServiceData += (char)(UUID_SERVICE_SHORT & 0xff);
  strServiceData += (char)((UUID_SERVICE_SHORT >> 8) & 0xff);
  strServiceData += (char)0x02; // LINE Simple Beacon FrameのFrame Type
  strServiceData += LINE_BEACON_HWID[0]; // LINE Simple Beacon FrameのHWID(5B)
  strServiceData += LINE_BEACON_HWID[1];
  strServiceData += LINE_BEACON_HWID[2];
  strServiceData += LINE_BEACON_HWID[3];
  strServiceData += LINE_BEACON_HWID[4];
  strServiceData += (char)0x7f; // LINE Simple Beacon FrameのMeasured TxPowe

  // LINE Simple Beacon FrameのDevice Message(1-13)
  int i = 0;
  for( i = 0 ; i < sizeof(LINE_BEACON_DEVICE_MESSAGE) ; i++ )
    strServiceData += LINE_BEACON_DEVICE_MESSAGE[i];

  advertisementData.addData(strServiceData);
  pAdvertising->setAdvertisementData(advertisementData);
  pAdvertising->start();

  vTaskDelay(portMAX_DELAY); //delay(portMAX_DELAY);
}

void setup() {
  M5.begin();

  Serial.begin(9600);
  
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setRotation(3);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(1);
  M5.Lcd.println("[LineBeacon]");
  Serial.println("LineBeacon");

  xTaskCreate(taskServer, "server", 40000, NULL, 5, NULL);
}

void loop() {
  M5.update();

  delay(1000);
}

以下の部分を環境に合わせて書き換えてください。

・LINE BEACON HWID:LINEビーコンのハードウェアID(5バイト)
・LINE_BEACON_DEVICE_MESSAGE:LINEビーコンのDevice Message(1~13バイト)

LINE BEACON HWIDは、先ほど払い出したハードウェアIDです。
LINE_BEACON_DEVICE_MESSAGEは、自由に定義でき、指定したバイト列が、LINEボットに通知されます。指定しない場合は、1バイトの0x00を指定します。

これで、LINEアプリがインストールされたスマホが、LINEビーコンを自動的に検知し、LINEボットに知らされます。受け取れるように、以下を追記しておきます。

api/controllers/linebot/index.js
app.beacon( async (event, client) =>{
	console.log(event);

	var message = app.createSimpleResponse("ビーコン(" + event.beacon.dm + ")の受信圏内に入りました");
	return client.replyMessage(event.replyToken, message);
});

app.beacon() の部分が、LINEビーコンを検出したことを受け取る部分です。

LINEアプリ側では、以下となっている前提です。
・LINEボットがお友達として登録されている
・LINEアプリの 設定 → プライバシー管理 → 情報の提供 → LINE Beacon のチェックボックスがOnになっている

最後に

ほかにも、LINEボットに関する投稿をしていますので、参考にしてください。

 Dialogflowと連携してLINE Botを作る
 LINE Beaconを自宅に住まわせる
 TI SensorTagをブラウザから使う(2):with LINE Things
 Actions on Google向けに作ったDialogflowボットをLINEボットにする
 LINEボットでゲームブックを作ってみた
 LINEボットでtodoist連携
 LINEボットでGoogle Alertを通知
 LINEBotのリッチメニューエディタがないので自作した
 LINEボットとATOM Echoでボイスメッセージを作る

以上

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?