【Unity】UnityアプリとGCFを連携させてデバッグ端末管理システムを作った話【GoogleCloudFunction】【GoogleCloudSQL】

# TL;DR
- UnityからGCFを呼ぶ時はUnityWebRequestの設定を気をつけよう 

https://qiita.com/Cova8bitdot/items/2aa8365f2dbbc1f2d81a

- NFCタグをスマホに貼る場合は金属対応シールを貼ったほうが読み取り精度が上がります
- 非エンジニア向けにスプレッドシートで見せるのは有効
- リマインダーBOTは端末棚卸しコストを減らせられるのでオススメ

# 概要

本記事は　`Qiita Engineer Festa 2023〜私しか得しないニッチな技術でLT〜` で登壇した内容の文字起こし+α版になります。

スライドはこちらから

https://speakerdeck.com/cova8bitdots/20230714-qiita-lt


自分の所属するGraffity(株)は社員15人満たない小さなスタートアップですが、ARアプリを中心とした開発を行っているため、デバッグ用の端末が数多くあります。

- iPhone
- Android (Galaxy, ASUS, HUAWEI...)
- Nreal Air/Light
- Google Glass Enterprise Edition 2
- Meta Quest2/ Quest Pro
- HTC XR Elite

上記のようにスマートフォンだけでなく、ARグラスやスタンドアローンVRデバイス（パススルーが可能なもの）など、種別も多いです。
このように種類も数も多いと `誰` が `いつ`, `何の端末を借りている/所持している` のか？という情報が無いと、「あの端末無い〜」　とか　「俺その端末持ってないよ」　みたいなコミュニケーションが多発し、無駄に労力を使ってしまいます。

また、コロナをきっかけにリモートワークも加速し、場合によっては端末を自宅に持ち帰って開発するようなケースもあるため、 `デバッグ端末が必ずしもオフィスにはない` ような状態もあります。

これを放置していると、端末を持って返ってると思っていたら紛失した等もあるため、所在をハッキリさせることで、無駄なコミュニケーションを減らし、端末の棚卸しのコストも下げることも可能です。

# 制作したデバッグ端末管理システム
![DeviceManageSystem.drawio (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/603bb341-ac71-2161-0761-44f38e831845.png)


今回作ったのは上記のようなシステムです。

まずは、管理用に全デバッグ端末にNFCタグを貼って管理しています。
そしてUnityで制作した端末貸し借りアプリでNFCタグと社員証を読み取ることでGCFのエンドポイントをコールすることで貸出情報を管理しています。

貸出情報は誰でも閲覧できるように、DB更新タイミングで一緒にスプレッドシートを自動更新して、そのスプレッドシートを全体に公開しています。

## NFCタグを端末に貼る

![スクリーンショット 2023-07-11 19.51.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/80a61e64-c17c-4204-0f2e-0cbd41b603c9.png)

上記の写真にある通り、デバッグ端末に固有のIDを振るためにNFCシールを利用しています。
しかし金属のボディ等に直接貼ると、タグの読み取り精度が下がる問題があります。

そこで、金属製のものにNFCシールを貼る時は以下のような防護シールを噛ませると精度がかなり上がります。
https://nfctags.shop-pro.jp/?mode=cate&cbid=1427753&csid=0


## Unity でNFCタグを読み取って貸し借りインターフェースを作成

Unity でNFCタグを読み取る機能を作成する場合、個人でNativePluginを作っても良いですが、今回は以下のアセットを利用しました。

https://assetstore.unity.com/packages/tools/integration/digits-nfc-toolkit-131674

残念ながら現在はAssetStoreで非公開になっているため、他の代替プラグインを利用するしかないようです。

上記プラグインでNFCタグを読み取ってGCFのエンドポイントを叩くのですが、叩く時に注意点があります。
注意点は以下の記事で解説しているので参考にしてください。

https://qiita.com/Cova8bitdot/items/2aa8365f2dbbc1f2d81a


## GCP 上の処理

メインの処理はGoogleCloundFunction 上で実行するPythonです。

レンタル処理はざっくり以下のような形で書いています。

```rental_request.py

def rental_request(request: flask.Request):
    HEADERS = {'Content-Type': 'application/json'}

    request_json = request.get_json()

    # Connect DB
    db = database.Database()
    user = _get_user_by_id(db, request_json["user_tag"])
    device = _get_device_by_id(db, request_json["device_tag"])

    if user is None or device is None:
        json_response = {"message": "Invalid Send Data"}
        return json.dumps(json_response), 403, HEADERS

    is_success = device_db.rental_request(db, request_json["user_tag"], request_json["device_tag"])
    # DB 終了
    db.close()

    if is_success:
        result = _update_spread_sheet(user.get_name(), device.get_id() )
        json_response = {"message": "SQL is DONE"}
        return json.dumps(json_response), 200, HEADERS
    else:
        json_response = {"message": "Failed to Update SQL"}
        return json.dumps(json_response), 403, HEADERS
```

極々単純な処理で、 Unity側からPOSTしてきた社員証のIDと端末のNFCタグを利用してGCSql上に構築しているDBから社員情報と端末情報を引っ張ってきます。
両者が正常なデータであれば、貸出期限付きでDB上に情報を更新します。
DB更新が正常に行われた場合は、スプレッドシートも更新するという処理です。

DB操作はSQLAlchemy をベースとしたGraffity社内用のPythonライブラリを作成して利用しているため、これくらいのコード量で実現できています。

GCF上のPythonコードでスプレッドシートを操作する部分に関しては、公式ドキュメントと以下の技術ブログが参考になります。

https://developers.google.com/sheets/api/quickstart/python?hl=ja
https://zenn.dev/yamagishihrd/articles/2022-09_01-google-spreadsheet-with-python

## 返却催促リマインダーBOT

ただの貸し借りだけなら先ほどで十分なのですが、`借りっぱなし`を許容すると、端末を使いたい人に端末が回らなかったり、長期間借りていることから、本人も借りていることを忘れてたり、最悪紛失したりと悪いことが多く発生しがちです。
そのため、貸出期限を設けて、長期レンタルしたい場合は、一度返却してからの再貸出という手順をとらせます。
定期的に再貸出をすることで、少なくとも紛失したことに気づかないことや、端末の所在の更新につながるため非常に重要です。

しかしながら人間は忘れっぽいもので、1ヶ月程度貸出期間を設けると、返却タイミングを忘れてしまいます。
そのためリマインダーBOTの作成が必要になります。

システムは先ほどの図でいうと上半分のところです。

![DeviceManageSystem_Reminder.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/69e1ee15-b4cb-e5e1-8cee-a2f98a241993.png)

定期実行はCloudSheduler を用いて設定。CloudSchedulerがGCFを起動してDBにアクセスして催促対象を選定。
通知自体はSlack BOTを通じてメンバーにメンションという流れになります。


実際にBOT通知が行われている風景はこのような形です。

![deviceReturn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/b715c74f-a926-e06c-7215-635750e6933f.png)


# 実際に作ってみて

まずは「端末どこ？」という会話が激減しました。
またスプレッドシートを用意したおかげでメンバー個人が確認できるようになったため、デバッグ端末管理人に都度聞くみたいな無駄な労力が減りました。

また `端末紛失疑惑` と `紛失疑惑の端末捜索` する回数も圧倒的に減ったため、より開発に割ける時間が増えました。

# まとめ

会社の規模やデバッグ端末の数が増えると、デバイス管理が非常に重要になります。
無駄な労力や開発時間を減らすような負の要因を減らすためにも、各企業それぞれが端末管理システムを作っておくと良いでしょう。