AITRIOSのRestAPIをとにかく短時間で叩いてみる

この記事は、2024年6月28日に開催された、AITRIOSもくもく会に参加し、初めてAITRIOSを触る人が迷いそうと感じた点を補強し、AITRIOS ConsoleのREST APIを使用する手順をマニュアルを見ずにできるようにという思いでまとめてみました。

# この記事の対象者
SONY エッジAIセンシングプラットフォーム「AITRIOS(アイトリオス)™」対応 カメラを[AITRIOS Portal](https://portal.aitrios.sony-semicon.com/)にデバイスしている方。PORTAL内のProjectへのアクセス権とPythonが使える環境が必要です。

## AITRIOS Console REST API
言わずもがな、これは、AITRIOS Consoleでできることを自身のプログラムで実現するためのAPI群で、公式のガイドは下記にあります。[公式: Console REST API 使い方ガイド](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/documents/console-rest-api-usage-guide/)

## 今回のサンプル
この記事では、Consoleに登録されているデバイスの状況を取得する**GetDevice** APIを使って、ゲットしたレスポンスを単純にファイルに保存するものと、Enroll済のカメラデバイスの接続先Wi-Fiを変更した際にConsoleのManage DeviceにあるSetup Deviceで作成する**QRコードの生成**をConsoleを使わずに行って、ファイルに保存するコードを紹介します。認証方法が公式とは異なりますが、この記事以外の資料を読まずとも簡単に個別情報を置き換えるだけで簡単に結果を得られるのでまず試してみたいという方に試していただければと思います。

## サンプル共通の事前準備
事前準備として、下記の４つの情報を確認・収集します。

* Console エンドポイント(api_url): https://console.aitrios.sony-semicon.com/api/v1
* Portal エンドポイント(token_url): https://auth.aitrios.sony-semicon.com/oauth2/default/v1/token
* client_id: 20桁の英数字
* client_secret: 64桁の英数字

Console エンドポイント(api_url)は、REST APIの大元のURLで、使用したい機能ごとに最後のv1意向のURLを仕様に沿って変えて行きます。下記は日本のConsoleエンドポイントの例で、他のリージョンは別のURLとなりますので[公式のエンドポイント情報](https://developer.aitrios.sony-semicon.com/file/download/edge-ai-sensing-portal-console-end-point-info)を参照してください。認証のためのPortal エンドポイント(token_url)は、全リージョン共通です。

そして、client_idとclient_secretが必要となりますが、こちらはProjectのOwnerもしくはAdminの場合は、Portalから自身で発行することができますが、Memberの場合は、OwnerもしくはAdminにリクエストして入手します。

Ownerもしくは、Adminの場合は、下記の画面を参考に、ProgectのPORTALからクライアントアプリ管理メニュにに入り、新規登録ボタンを押し、出てくるダイアログボックスのクライアントアプリ名称に適当な名前をつけ、システム権限に二つともチエックをして登録するボタンを押します。そうするとシークレット情報が表示されますので、このタイミングでコピーしておきます。（後で参照できるのは一部分のみです）そして、一覧に戻って、ID(client_id)を確認します。
メンバーの場合はこの手順をOwnerもしくはAdminに伝え、各値を発行してもらいます。Memberの場合は、新規登録のボタンが表示されません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314541/77f56cec-5a2c-7298-d899-3c610cfbe9f5.png)

## サンプル #1 ー デバイス情報の取得(GetDevice)

今回のサンプルでは、特定のデバイスに絞ってデバイス情報を取得するようになっていますので、対象となるデバイスのIDをConsoleで調べて、プログラムの変数にセットします。Activeになっていないカメラの情報も取れます。デバイスIDは、下図の通りConsoleのManage Deviceで確認することができます。この値をプログラム内のdevice_idにセットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314541/6304206f-1ced-f892-4200-cc312d719fc4.png)

そして、準備で入手した、
* client_id: 20桁の英数字
* client_secret: 64桁の英数字

をセットして、実行すれば画面に結果が見やすいフォーマットで表示されると共に、同じディレクトリー(フォルダー）にdevice_apps_response.jsonとして結果が保存されます。

``` python：GetDeviceData.py
# Enroll済のカメラデバイスの情報をデバイスIDを指定して取得し、ファイルに保存するコード

# 必要なライブラリーが入っていない場合は自動的にインストールする
import sys
import subprocess

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])

required_packages = ['requests', 'oauthlib', 'requests_oauthlib']

for package in required_packages:
    try:
        __import__(package)
    except ImportError:
        print(f"{package} is not installed. Installing...")
        install(package)
        print(f"{package} has been installed.")

# ここからが本体

import requests
import json
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

# 認証情報
client_id = "20桁の自身の値に置き換え"
client_secret = "64桁の自身の値に置き換え"
token_url = "https://auth.aitrios.sony-semicon.com/oauth2/default/v1/token/"

# GetDeviceのAPI URL
api_url = "https://console.aitrios.sony-semicon.com/api/v1/devices/{device_id}"

# デバイスID（実際に確認したいデバイスIDに置き換えてください）
device_id = "Aid-80070001-0000-2000-9002-000000000000"

# アクセストークンの取得
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client, scope="system")
token = oauth.fetch_token(token_url=token_url, client_id=client_id, client_secret=client_secret, scope="system")

# APIリクエストの送信
headers = {
    "Authorization": f"Bearer {token['access_token']}",
    "Content-Type": "application/json"
}

try:
    # デバイスIDをURLに挿入
    print(api_url.format(device_id=device_id))
    response = requests.get(api_url.format(device_id=device_id), headers=headers)
    data = response.json()
    print("RESPONSE=",response)
    print(json.dumps(data, indent =4 ))
    data = response.json() 
    
#   データをファイルに保存
    with open('device_apps_response.json', 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=4)

#エラー処理

except requests.exceptions.RequestException as e:
    print(f"リクエストエラーが発生しました: {e}")
except json.JSONDecodeError as e:
    print(f"JSONデコードエラーが発生しました: {e}")
    print(f"レスポンス本文: {response.text}")
except Exception as e:
    print(f"予期しないエラーが発生しました: {e}")
```

## サンプル #2 ー QRコードの生成(GetQrCodeForProvisioning)
次は、QRコードの生成と保存を行います。QRコードを使うシーンは大きく二つありますが、一番最初にカメラをConsoleに登録(Enroll)するためのQRコードの生成用のAPIは、提供されていませんので、最初の登録はConsoleから行うか、カスタマーサポートからデバイスの証明書を発行してもらい登録する必要があります。
今回のサンプルは、すでにEnrollされているデバイスのWi-Fi接続先を変更した場合に行うQRの読み込み時に使用するQRコードの生成です。

準備で入手した、
* client_id: 20桁の英数字
* client_secret: 64桁の英数字

をセットし、下記のWi-Fi情報を正しい値に置き換えます。
* "wifi_ssid": "2.4GHzのWi-FiアクセスポイントのSSIDを入れる",
* "wifi_pass": "上記のパスワードを入れる"

そして、プログラムを実行すればBase64でエンコードされた文字での結果が表示されると共に、同じディレクトリー(フォルダー）にdevice_apps_response.jsonとして結果が保存され、さらにイメージファルのdecoded_qr_code.pngも保存されます。

``` python：QR_Generation.py
# Enroll済のカメラデバイスの接続先Wi-Fiを変更した際にManage DeviceのSetup Deviceで
# 生成するQRコードをConsoleを使わずに生成し、ファイルに保存するコード

# 必要なライブラリーが入っていない場合は自動的にインストールする
import sys
import subprocess

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])

required_packages = ['requests', 'oauthlib', 'requests_oauthlib']

for package in required_packages:
    try:
        __import__(package)
    except ImportError:
        print(f"{package} is not installed. Installing...")
        install(package)
        print(f"{package} has been installed.")

# ここからが本体

import requests
import json
import base64
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

# 認証情報 
client_id = "20桁の自身の値に置き換え"
client_secret = "64桁の自身の値に置き換え"
token_url = "https://auth.aitrios.sony-semicon.com/oauth2/default/v1/token/"

# QRコード生成のAPI URL
api_url = "https://console.aitrios.sony-semicon.com/api/v1/provisioning/qrcode"

# アクセストークンの取得
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client, scope="system")
token = oauth.fetch_token(token_url=token_url, client_id=client_id, client_secret=client_secret, scope="system")

# APIリクエストの送信
headers = {
    "Authorization": f"Bearer {token['access_token']}",
    "Content-Type": "application/json"
}

# クエリパラメータ
params = {
    "ntp": "1.jp.pool.ntp.org",
    "wifi_ssid": "2.4GHzのWi-FiアクセスポイントのSSIDを入れる",
    "wifi_pass": "上記のパスワードを入れる"
}

try:
    # データゲット
    response = requests.get(api_url, headers=headers , params = params)
    data = response.json()
    print("RESPONSE=",response)
    print(json.dumps(data, indent =4 ))
    qrdata = data.get("contents")
    
#   Responseデータ全体をファイルに保存
    with open('device_apps_response.json', 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=4)
    
# BASE64デコード
    decoded_data = base64.b64decode(qrdata)

# デコードされたQRコード画像をファイルに保存
    output_file = "decoded_qr_code.png"
    with open(output_file, "wb") as file:
        file.write(decoded_data)

    print(f"QR Code has been successfully saveed on {output_file} ")

# エラー処理

except requests.exceptions.RequestException as e:
    print(f"リクエストエラーが発生しました: {e}")
except json.JSONDecodeError as e:
    print(f"JSONデコードエラーが発生しました: {e}")
    print(f"レスポンス本文: {response.text}")
except Exception as e:
    print(f"予期しないエラーが発生しました: {e}")
```

## 先に進むための有用な情報

当然のことながら公式には様々かつ緻密な資料が揃えられています。ここから発展させて行く際に便利なLINKをまとめてみました。

[Console APIの仕様書](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/documents/console-rest-api-specification/)：エンドポイント情報や、与えるパラメーターやレスポンスなどが詳細に書かれています。
[Console REST API 使い方ガイド](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/documents/console-rest-api-usage-guide/)：公式ガイドです。APIが種類ごとに整理されて紹介されていますので、眺めてみることをお勧めします。このガイドにはアクセストークンの取得方法なども書かれていますが、サンプル内では別の方法で実装しています。

## その他

今回のサンプルプログラムでは、実行の度にアクセストークンを発行させていますが、Console REST API Tokenの有効期限は1時間ですので、本来は有効期間内は一度発行したものを使い続けること推奨されます。

アクセストークンを取得する際に指定しているscopeは、"system"が唯一の値ですべてのRestAPI共通であることを公式サポートに確認済みです。

先に書いた通り、「Enrollment QRコードによる登録」のSetup EnrollmentのAPIは提供されていません。また、「間欠動作モードの設定」、「エッジデバイスの推論 開始/終了時間設定」そして「エッジデバイスの情報確認」のevent log 確認も現時点提供されていないとのことです。