専用アプリはもう要らない?LINE BotからAkerunを操作する(その1)

この記事は Akerun Advent Calendar 2019 - Qiita の17日目の記事です。

はじめに

はじめまして、先月Photosynthに入社したばかりのWebエンジニアのBunと申します。主にApp(iOS)開発を担当しています。 最近、Akerun Developersのメンテも行なっていますので、 Akerun API + いろんなサービスと連携して行こうと思います。

まず第一弾として、LINE Botと連携してみました。 LINEを使っている人は多いので、普段使っているLINEだけでAkerunの施錠解錠ができれば、めっちゃ楽になりますね。 以前LINE Botのグループ機能を使ったBot(LINE BOT AWARDS グループトーク部門賞)を作成した経験もあって、グループで使えるAkerun Botにする予定でしたが、内容が長くなってしまうので、2回に分けました。

  • LINE Bot単体からAkerunを操作する。(今回の記事)
  • LINE Botグループで機能を使って、グループ内のユーザーなら誰でもAkerunを操作できる。(後日公開予定)
    ※こちらの方が、ユーザーをグループに追加するだけで、簡単にAkerunを施錠解錠できるので、専用アプリが要らなくなるかも?!

ちなみに14日目の記事ではAlexaと連携した内容が書かれていますので、興味がある方はぜひご参照ください。

akerun.hateblo.jp

Akerun APIを活用できれば、いろいろ面白いサービスを提供できそうですね。

akerun.hateblo.jp

事前準備

まず、AkerunProの接続、必要なAPIの利用申請、アカウント作成、サーバーサイトの準備を行います。

Akerun Proを接続

Akerun Remote経由でAkerun Proを操作できるように設定します。詳細についてAkerunサポートページをご参照ください。

Akerun APIを申請

Akerun Developersのお申し込みページからAkerun API利用申請を行います。
※Akerun ProとAkerun 入退室管理システムご利用いただいている場合のみお申込み可能です。

developers.akerun.com

Akerun APIのアクセストークンを作成

Akerun Developersの認証ページの手順に従って、アクセストークンを作成します。

アクセストークンのスコープを設定

Akerun Managerの「連携アプリ」ページでスコープを設定する必要があります。 詳細についてAkerun Developersのスコープ設定ページをご参照ください。

LINE Providerを作成

LINEアカウントがあれば、LINE Developersにログイン(あるいはアカウント作成)可能です。

developers.line.biz

  • Provider作成

LINE DevelopersのコンソールからProviderを作成します。

f:id:photosynth-inc:20191215221648p:plain
LINE Provider 作成

サーバーサイト(heroku)を準備

LINE Bot用のサーバーが必要ですので、手軽に使えるPaaSのherokuで実装したいと思います。
※無料範囲内の場合、一定時間アクセスが無いとスリープモードに入り、次回アクセス時少し時間が掛かります。

jp.heroku.com

アカウントがない場合、上記herokuからアカウントを作成します。

  • Messaging API channel作成

3つのチャンネルの中からBot用のMessaging API channelを作成します。

f:id:photosynth-inc:20191215221740p:plain
Messaging API channel 作成

botアプリを作成

heroku-cliをインストール&ログイン

heroku-cliからダウンロード/インストールするか、以下のコマンドでダウンロード/インストールします。 loginすると、herokuのログインページが表示されるので、ログインします。
※必要な環境変数は後ほど設定します。

brew tap heroku/brew && brew install heroku
heroku login

f:id:photosynth-inc:20191216145452p:plain
heroku login

heroku appを作成

mkdir akerun-bot-demo
cd akerun-bot-demo

git init

heroku create akerun-bot-demo
Creating ⬢ akerun-bot-demo... done
https://akerun-bot-demo.herokuapp.com/ | https://git.heroku.com/akerun-bot-demo.git

git remote -v
heroku  https://git.heroku.com/akerun-bot-demo.git (fetch)
heroku  https://git.heroku.com/akerun-bot-demo.git (push)

※git initとheroku createの順番が逆になると、remoteにリポジトリが設定されないので、手動で設定します。(git remote add heroku {app url})

SDK/Libsイントール

pythonで実装するので、以下のLINE SDKと必要なlibsをインストールします。
pythonは事前にインストールします。pyenvなどを使うと楽になります。

pip install line-bot-sdk
pip install flask
pip install requests
pip install gunicorn

botを実装

  • ベース部分実装

オウム返しのメインファイルbot.pyを作成します。

from flask import Flask, request, abort

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import *

app = Flask(__name__)

line_channel_id = os.getenv('LINE_CHANNEL_ID')
line_channel_secret = os.getenv('LINE_CHANNEL_SECRET')
line_channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN')
akerun_api_access_token = os.getenv('AKERUN_API_ACCESS_TOKEN')

line_bot_api = LineBotApi(line_channel_access_token)
handler = WebhookHandler(line_channel_secret)

# test
@app.route("/")
def hello_bot():
    return "akerun bot!"

@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        print("Invalid signature. Please check your channel access token/channel secret.")
        abort(400)

    return 'OK'

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))


if __name__ == "__main__":
    port = int(os.getenv("LINE_BOT_PORT", '5000'))
    app.run(host="0.0.0.0", port=port)
  • Procfile作成(プログラムの実行方法を定義)
vi Procfile
web: gunicorn bot:app --log-file=-
  • Requirements.txt作成(インストールするライブラリの記載)
pip freeze > requirements.txt
  • runtime.txt作成(Pythonのバージョンを記載

pythonバージョンは自分の環境に合わせてください。

vi runtime.txt
python-3.8.0
  • 環境設定

heroku上のbotアプリのSettingsページで環境変数を設定します。
※一旦任意の文字列を設定し、下記手順でAkerun API、LINE関連のトークンが取得できたら、更新します。

f:id:photosynth-inc:20191216141000p:plain
環境変数設定

以下のherokuコマンドからも設定可能です。

heroku config:set LINE_CHANNEL_SECRET="" --app {app name}
heroku config:set LINE_CHANNEL_ACCESS_TOKEN="" --app {app name}
heroku config:set LIN_BOT_PORT=5000 --app {app name}

ローカル環境で確認する場合、以下のコマンドで環境変数を登録しておきます。

export LINE_CHANNEL_SECRET=xxx
export LINE_CHANNEL_ACCESS_TOKEN=xxx
export LIN_BOT_PORT=5000

ターミナルを再度開く時、上記の設定が消えてしまうので、必要な場合、~/.bash_profile(Mac)などに設定します。

vi ~/.bash_profile
export LINE_CHANNEL_SECRET=xxx
export LINE_CHANNEL_ACCESS_TOKEN=xxx
export LIN_BOT_PORT=5000
source ~/.bash_profile

デプロイ

変更内容をコミットし、herokuへpushすると、自動的にherokuへデプロイされます。 https://akerun-bot-demo.herokuapp.com/にアクセスし、テストメッセージ「akerun bot!」が表示されればOKです。

git add .
git commit -m "first commit"
git push heroku master

ローカル動作確認環境作成

コードを変更する度にherokuへデプロイするのは面倒なので、ngrokを使用して、localhostを外部に公開できるようにします。

  • ngrokにログイン(或いはサインイン)し、ngrokをダウンロードする。
  • ダウンロードしたngrok(zip)を任意のディレクトリに解答する。
  • ngrokにログイン後、トークンをコピーし、以下の実行する
cd ngrok解凍ディレクトリ
./ngrok authtoken xxx
  • ローカルでbot.pyを実行し、外部に公開する。
    ※LINE Botのwebhookに設定するので、外部公開URL(https://xxxx.ngrok.io)をメモしておく。
python bot.py
ngrok http 5000

ngrok by @inconshreveable                                       (Ctrl+C to quit)
                                                                                
Session Status                online                                            
Account                       xxx (Plan: Free)                         
Version                       2.3.35                                            
Region                        United States (us)                                
Web Interface                 http://127.0.0.1:4040                             
Forwarding                    http://xxx.ngrok.io -> http://localhost:5000 
Forwarding                    https://xxxx.ngrok.io -> http://localhost:5000

Akerun施錠解錠処理を実装

まず、施錠解錠するための最小限の実装を行います。Akerun APIの詳細についてAkerun Developersをご参照ください。

# 組織一覧を取得
def akerun_bot_get_organizations(akerun_token):
    ak_url = 'https://api.akerun.com/v3/organizations'
    ak_headers = {'Authorization': 'Bearer ' + akerun_token}
    return akerun_bot_api(ak_url, ak_headers)

# 組織詳細情報を取得
def akerun_bot_get_organization_info(akerun_token, org_id):
    ak_url = 'https://api.akerun.com/v3/organizations/{}'.format(org_id)
    ak_headers = {'Authorization': 'Bearer ' + akerun_token}
    return akerun_bot_api(ak_url, ak_headers)

# 組織に属するAkerunの一覧を取得
def akerun_bot_get_akeruns(akerun_token, org_id):
    ak_url = 'https://api.akerun.com/v3/organizations/{}/akeruns'.format(org_id)
    ak_headers = {'Authorization': 'Bearer ' + akerun_token}
    return akerun_bot_api(ak_url, ak_headers)

# 施錠リクエストを送信
def akerun_bot_lock(akerun_token, org_id, akerun_id):
    ak_url = 'https://api.akerun.com/v3/organizations/{}/akeruns/{}/jobs/lock'.format(org_id, akerun_id)
    ak_headers = {'Authorization': 'Bearer ' + akerun_token}
    return akerun_bot_api(ak_url, ak_headers)

# 施錠結果を取得
def akerun_bot_lock_state(akerun_token, org_id, job_id):
    ak_url = 'https://api.akerun.com/v3/organizations/{}/jobs/lock/{}'.format(org_id, job_id)
    ak_headers = {'Authorization': 'Bearer ' + akerun_token}
    return akerun_bot_api(ak_url, ak_headers)

# 解錠リクエストを送信
def akerun_bot_unlock(akerun_token, org_id, akerun_id):
    ak_url = 'https://api.akerun.com/v3/organizations/{}/akeruns/{}/jobs/unlock'.format(org_id, akerun_id)
    ak_headers = {'Authorization': 'Bearer ' + akerun_token}
    return akerun_bot_api(ak_url, ak_headers)

# 解錠結果を取得
def akerun_bot_unlock_state(akerun_token, org_id, job_id):
    ak_url = 'https://api.akerun.com/v3/organizations/{}/jobs/unlock/{}'.format(org_id, job_id)
    ak_headers = {'Authorization': 'Bearer ' + akerun_token}
    return akerun_bot_api(ak_url, ak_headers)

# Akerun APIをCall
def akerun_bot_api(url, headers):
    obj_session = Session()
    obj_request = Request("POST",
                          url,
                          headers=headers
                          )
    obj_prepped = obj_session.prepare_request(obj_request)
    obj_response = obj_session.send(obj_prepped,
                                    verify=True,
                                    timeout=60
                                    )
    print('status_code:' + str(obj_response.status_code))
    print('obj_response.text:' + obj_response.text)
    response_dict = json.loads(obj_response.text)
    print(response_dict)
    #return response_dict.job.id
    return response_dict['job']['id']

LINE Botを設定

Messaging API channelを作成

LINE DevelopersのProviderにアクセスし、channelを作成します。

f:id:photosynth-inc:20191216145002p:plain
Messaging API channel作成

f:id:photosynth-inc:20191216011412p:plain
Messaging API channel選択

必須項目を入力し、channelを作成します。

f:id:photosynth-inc:20191216011233p:plain
Messaging API channel作成完了

secretとtokenを取得

作成したchannelの設定ページからChannel secretとChannel access tokenを取得します。

f:id:photosynth-inc:20191216012406p:plain
Basic setting ページ

f:id:photosynth-inc:20191216012318p:plain
Channel secret

f:id:photosynth-inc:20191216012454p:plain
Messaging API ページ

f:id:photosynth-inc:20191216012342p:plain
Channel access token

webhookを設定

LINEユーザーのメッセージ(Akerun操作コマンド)をbot(herokuアプリ)に送信するために、Messaging API ページでwebhookを設定します。

  • herokuアプリへのwebhook

    f:id:photosynth-inc:20191216013603p:plain
    webhook heroku app

  • localhostを環境を使った場合、ngrokのURLを設定

    f:id:photosynth-inc:20191216013744p:plain
    webhook localhost

botの応答設定

ユーザーがメッセージを送信する度に自動的に応答メッセージが返ってくるので、一旦無効にします。

  • 応答メッセージ編集画面に遷移

    f:id:photosynth-inc:20191216102531p:plain
    応答メッセージ編集画面に遷移

  • 応答メッセージをOFF

その他設定はデフォルトのまま(ON)でOKです。

応答メッセージをOFFにする
応答メッセージをOFFにする

リッチメニュー作成

ユーザーが施錠解錠ボタン(画像)を押して、Akerunを施錠解錠できるようにリッチメニューを作成します。
※詳細についてリッチメニューを新規作成するをご参照ください。

  • LINE Official Account Managerにログインし、アカウントリストからアカウント(bot)を選択する

    f:id:photosynth-inc:20191216145244p:plain
    LINE Official Account Managerに遷移し、アカウントを選択

  • リッチメニューを新規作成

リッチメニューを新規作成

  • 基本設定を行う

タイトルと表示期間を設定し、テンプレートを選択します。その他設定はデフォルト設定でOKです。

f:id:photosynth-inc:20191216150818p:plain
基本設定を行う

  • テンプレートを選択

f:id:photosynth-inc:20191216164126p:plain
テンプレートを選択

  • 施錠解錠コマンドを設定

アクションBとDのタイプをテキストに設定し、それぞれ「>lock」、「>unlock」コマンドのテキストを入力します。
※Prefix「>」はその他コマンドと区別する為に設定していますが、無くても問題ありません。

f:id:photosynth-inc:20191216164142p:plain
施錠解錠コマンドを設定

  • 施錠解錠の画像を作成する

「画像作成」画面で施錠解錠の画像をアップロードし、画像の下にテキストを追加します。位置は設定メニューで簡単に調整可能です。

f:id:photosynth-inc:20191216164200p:plain
施錠解錠画像設定

  • 設定を保存し、LINE上で確認する

上記の設定を保存します。LINE Developersに戻って、「Messaging API設定」ページのQRコードからbotを追加します。

f:id:photosynth-inc:20191216144541p:plain
QRコードからbotを追加

以下のメニューが表示されます。

f:id:photosynth-inc:20191217080350p:plain
メニュー

連携する

Akerun APIから施錠解錠の実装とLINE Botの施錠解錠(リッチメニュー)を作成しましたので、LINEから施錠解錠メニュー(画像)を押した時の動作を実装します。 handle_messageに以下の処理を追加します。施錠(>lock)/解錠(>unlock)コマンドを受信したら、それぞれ施錠解錠リクエストを送信します。
※全体コードは別途公開する予定ですが、Akerunの組織ID、AkerunIDはAkerun Developersを参考に取得してください。
※また、リクエストを送信してから施錠解錠結果をポーリングする必要がありますが、簡単にする為、リクエスト直後そのまま結果をユーザーに返しています。

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    reply_msgs = []
    akerun_token = akerun_api_access_token
    org_id = 'xxxx'
    akerun_id = 'xxxx'

    if event.message.type == 'text':
        if event.message.text[0] == cmd_prefix:
            cmd = event.message.text
            if cmd == cmd_prefix + 'lock':
                # 施錠リクエストを送信
                akerun_bot_lock(akerun_token, org_id, job_id)
                reply_msgs.append(TextSendMessage(text=u'施錠'))
            elif cmd == cmd_prefix + 'unlock':
                # 解錠リクエストを送信
                akerun_bot_unlock(akerun_token, org_id, job_id)
                reply_msgs.append(TextSendMessage(text=u'解錠'))
    if len(reply_msgs):
        line_bot_api.reply_message(
            event.reply_token,
            reply_msgs)

施錠

botのメニューからLOCKを押します。少しタイムラグはありますが、施錠できました。

f:id:photosynth-inc:20191216152717p:plain
LOCKコマンド送信

f:id:photosynth-inc:20191216152800j:plain
AkerunPro施錠

解錠

botのメニューからUNLOCKを押します。こちらも少しタイムラグはありますが、解錠できました。

f:id:photosynth-inc:20191216152915p:plain
UNLOCKコマンドを送信

f:id:photosynth-inc:20191216152939j:plain
AkerunPro解錠

まとめ

長文になってしまいましたが、無事LINE BotからAkerunを施錠解錠ができました!

  • Akerun APIを利用するには、申し込み申請が必要で、アクセストークンを発行するまで結構手間がかかります。これについては改善していきたいと思います。アクセストークンさえ発行できれば、API自体はシンプルで使いやすいのではないかと思います。
  • 内容からも分かると思いますが、LINEの設定項目がたくさんあります。ただ、操作しやすいUIになっているので、それ程難しくはないですね。
  • その2ではLINE Botグループ機能を入れて、Botアプリを完成させたいと思います。Akerun APIのアクセストークン、組織ID、AkerunIDについて、ハードコーディングではなく、Bot上で選択出来るようにします。
  • その2が完了後、ソースコードgithubに上げる予定です。実際のBotも期間限定で公開してみようかと思います。

株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 recruit.jobcan.jp

Akerun Proの購入はこちらから akerun.com