AIスピーカーでネットワーク管理してみました

# はじめに
AIスピーカーを利用してネットワークの稼動状況や設定変更がコマンド入力や管理画面に接続することなく誰でも行うことができないか試してみました。

今回使用した機器は、Amazon EchoとHPE Aruba Networks製品（無線AP）。
バックエンドにはAWS Lambdaを利用しクラウド上でネットワーク管理できるAruba Central経由で
ネットワークの設定変更してみました。
実際の対話はこのようになります。

<img width="812" alt="スクリーンショット 2018-11-28 11.27.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/154411/b64b830e-ae55-2393-d0d0-37fdaf9552e8.png">


# 全体構成図
<img width="791" alt="スクリーンショット 2018-11-28 13.37.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/154411/1e07b053-de5b-c640-cc67-8981c15317e8.png">

①．Alexaに設定変更を依頼
②．Alexa Intentでユーザ発言を変数に変換してLambdaへリクエストを送信
③．LambdaはまずAruba Centralに接続するためのアクセストークンとリクエスト内容により設定テンプレートをS3から取得
④．S３より取得した設定テンプレート一時的にLambda内に保存
⑤．Lambda上のスクリプトがAruba CentralのAPIを使って接続し設定テンプレートを書き込み
⑥．Aruba Centralは設定されたテンプレートを各無線APに配信し変更を反映
⑦．Alexaが変更結果を返答


---


**●準備するアカウント**

- Amazon開発アカウント
   - Alexaスキルを開発するために必要　　
- AWSアカウント
   - AWS Lambdaを開発するために必要
- Aruba Centralアカウント
   - Aruba Centralへの接続やAPIを確認するために必要

# 作成方法
##Alexaスキルと対話モデルの作り方
Amazon開発アカウントでAlexa Skills Kit Developer Consoleに接続してAlexaスキルと対話モデルを作成します。
Alexaスキルの基本的な作成方法は公式サイトを参照してください。
[Alexaスキル開発トレーニング](https://developer.amazon.com/ja/alexa-skills-kit/training/building-a-skill)

今回のインテントの例とサンプル発話の例です。

```json

"name": "GuestwifiON",
                    "slots": [],
                    "samples": [
                        "ゲストをオンして",
                        "ゲストワイファイを有効",
                        "ゲストワイハイを有効",
                        "ゲストをオン",
                        "ゲストを有効にして"

 "name": "GuestwifiOFF",
                    "slots": [],
                    "samples": [
                        "ゲストをオフして",
                        "ゲストを無効にして",
                        "ゲストを停止して",
                        "ゲストワイファイをオフ",
                        "ゲストワイファイをオフして",
                        "ゲストをオフ",
                        "ゲストをオフに設定"
```
##AWS Lambda関数の作り方
AWS Lambdaの作成方法についてはこちらを参照してください。
[AWS Lambda ドキュメント](https://docs.aws.amazon.com/lambda/index.html#lang/ja_jp)
今回は、ランタイムとしてPython 3.6を使用

###アクセストークンについて
Aruba Centralに接続するためにはアクセストークンが必要となります。このアクセストークンは2時間毎に変更となる仕様となってますので今回は、定期的にアクセストークンを取得しS3に保存することにしAruba Centralに接続時にS3に保存されたトークンファイルを参照する仕組みにしました。
下記コードはLambdaでテンプレートを使用した作成した内容に書き加えた内容となります。

```python

#アクセストークン取得#
#### API_Token ####
def refresh_token(token_dict):
    client_id = token_dict['client_id']
    client_secret = token_dict['client_secret']
    refresh_token = token_dict['refresh_token']
    url = base_url+"oauth2/token?client_id="+client_id+"&client_secret="+client_secret+"&refresh_token="+refresh_token+"&grant_type=refresh_token"
    print(url)
    response = requests.request("POST", url)
    print(response)
    token_dict['refresh_token'] = response.json()['refresh_token']
    token_dict['access_token'] = response.json()['access_token']
    access_token = response.json()['access_token']
    text = json.dumps(token_dict)
    upload_s3(text,"central_token.json")
    return access_token

#S３にアップロード#
#### Upload Json to S3 ####
def upload_s3(text,key):
    s3 = boto3.client('s3')
    handler = StringIO(text)
    s3.put_object(
        Bucket = bucket_name,
        Key = key,
        Body = handler.read(),
        ContentType = 'application/json; charset=utf-8'
    )
#S３からトークンを参照#
#### read Json to S3 ####
def read_s3():
    s3 = boto3.resource('s3')
    content_object = s3.Object(bucket_name, 'central_token.json')
    file_content = content_object.get()['Body'].read().decode('utf-8')
    json_content = json.loads(file_content)
    return json_content['access_token']

```
###GuestWiFi変更について
事前に設定変更用のテンプレートをS3に準備し設定変更内容に応じてファイルを取得し
Aruba CentralのAPIを利用して設定変更を行うようにしました。すみません今回は設定変更したい部分だけでなくテンプレートを使用してコンフィグを全て変更してます。もっといい方法があると思いますが。。。


```python

#設定変更用テンプレート取得#
#### Guestwifi Json to S3 ####
def download_s3(intent):
    s3 = boto3.resource('s3')
    if intent == "GuestwifiON":
        file_name = "enable.txt"
    elif intent =="GuestwifiOFF":
        file_name = "disable.txt"
    file_path = file_path = '/tmp/' + file_name
    bucket = s3.Bucket(bucket_name)   
    bucket.download_file(file_name, file_path)
    content_object = s3.Object(bucket_name, file_name)
    print(subprocess.run(["ls", "-l", "/tmp"], stdout=subprocess.PIPE))
    return

#GuestwifiをONする場合#
#### Guestwifi ON ####
    session_attributes = {}
    download_s3(intent["name"])
    access_token = read_s3()
    fileName = '/tmp/enable.txt'
    fileDataBinary = open(fileName, 'rb').read()
    files = {'template':(fileName,fileDataBinary,'text/plain')}
    url = "https://app1-apigw.central.arubanetworks.com/configuration/v1/groups/tec-temp/templates"
    querystring = {"name":"temp01","device_type":"IAP","access_token":access_token}

    response = requests.request("PATCH", url, params=querystring, files=files)
    print(response.text)
    
    
    if response.status_code == requests.codes.ok:
        speech_output = 'ゲストワイファイを有効にしました';
        reprompt_text ='もう一度お願いします';
        should_end_session = True
    
    else:
        speech_output = 'ゲストワイファイを有効にできませんでした。';
        reprompt_text ='もう一度お願いします';
        should_end_session = True


#GuestwifiをOFFする場合#
#### Guestwifi OFF ####
def GuestwifiOFF(intent, session):
    session_attributes = {}
    download_s3(intent["name"])
    access_token = read_s3()
    fileName = '/tmp/disable.txt'
    fileDataBinary = open(fileName, 'rb').read()
    files = {'template':(fileName,fileDataBinary,'text/plain')}
    url = "https://app1-apigw.central.arubanetworks.com/configuration/v1/groups/tec-temp/templates"
    querystring = {"name":"temp01","device_type":"IAP","access_token":access_token}

    response = requests.request("PATCH", url, params=querystring, files=files)
    print(response.text)
    
    
    if response.status_code == requests.codes.ok:
        speech_output = 'ゲストワイファイを無効にしました';
        reprompt_text ='もう一度お願いします';
        should_end_session = True
    
    else:
        speech_output = 'ゲストワイファイを無効にできませんでした。';
        reprompt_text ='もう一度お願いします';
        should_end_session = True
```

#まとめ
今回は、GuestWiFiの有効/無効という設定変更をサンプルとして作成してみましたがAruba Centralには様々なAPIが用意されていますので色々と活用できそうです。
今回は、入力部分でAlexaを使用しましたがChatbotなどでも対応可能です。

#参考
[[API] Alexa と Aruba Central を使ったネットワークの音声管理](https://community.arubanetworks.com/t5/%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9%E3%83%A0/API-Alexa-%E3%81%A8-Aruba-Central-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E9%9F%B3%E5%A3%B0%E7%AE%A1%E7%90%86/td-p/400980)
[Aruba+Chatbot DEMO](https://community.arubanetworks.com/t5/%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9%E3%83%A0/API-Chatbot%E3%81%A7%E6%97%A5%E3%80%85%E3%81%AE%E9%81%8B%E7%94%A8%E3%81%AE%E5%83%8D%E3%81%8D%E6%96%B9%E6%94%B9%E9%9D%A9/td-p/414309)