スクリーンショット_2019-11-29_18

ソフトウェア開発 - sense. CONNECTの舞台裏

今回、sense.のデジタルインスタレーション作品「CONNECT」の受付システム、楽曲配信システム、を担当しました、中嶋俊太 / Shunta Nakajima です。
この記事では、私がどういう工程を踏んで今回のシステム周りを完成させたのかを簡単に紹介したいと思います。

受付システム

開発した物
・受付用iPadアプリケーション
・受付スタッフ用iPhoneアプリケーション
・Eメール送信用サーバー
・QRコードを表示するウェブサイト及びバックエンド
・QR照合システム

利用言語/技術
・swift5
・python3
・firebase realtime database
・Raspberry pi
・git

使用したエディターなど
・Xcode
・Visual Studio Code
・vim

その他利用したフレームワークやライブラリ
・RxSwift
・lottie
・SwiftGen
・SnapKit
・flask

予約の手順

スクリーンショット 2019-11-29 16.40.11

各公演時間の空き状況管理など、予約を円滑に行うためのiPad受付アプリケーションを作成しました。

使用手順

①iPadアプリに入力した情報をFirebase(データベース)に送信し、仮予約を行います。
②スタッフに入場料を手渡しで支払いされた段階で、スタッフが予約完了処理をします。
③予約完了処理と同時に、お客様に入場用QRコードのリンクが送信されます。

QRサイト

画像3

お客様に送信されるQRサイトです。ゲートのリーダーにかざすことで入場できます。

入場の手順

スクリーンショット 2019-11-29 16.44.27

入場の際は、お客様に送信された入場用QRコードをRaspberryPiに接続したQRコードスキャナで読み込み、データベースと照合した後にゲートへ開閉信号を送信するという手順を踏んでいます。


以上、ざっくりと今回の入場フローを説明しました。
続いてそれぞれのアプリケーションについて軽く説明します。

受付iPadアプリについて

以下の環境で開発をしております。

xcode: 11.0
cocoapods: 1.7.5

また、iPhoneで動作する必要は無いため、iPadのみの動作を保証しました。
今回の受付アプリは、このイベントのみの使用のため、
①UIの更新などもない
②開発期間がかなり短い
この二点からアーキテクチャ等をそこまで重視せずに実装しました(再利用するコードや一部の通信周りなどは切り分けています)。

当日は複数台iPadを用意し、複数個の受付口を設ける予定でした。
複数台で同じ時間に予約をした際、人数が既定値を超えないように設計をしなければいけない為、DBとの通信(DBの変更をリッスンする必要がある)にリアルタイム制が求められます。
そこで、Firebase Realtime Databaseを用いました。FirebaseのSDKでは、DBのデータ変更通知をリッスンしてくれるため、自前実装が不要です。
これを用いて、別端末で予約が取られた際に最初のページ(以下の画像)にリアルタイムで残り人数を表示することを可能にしました。

スクリーンショット 2019-11-30 22.28.59

また、予期せぬ事態(設備の破損による公演遅延、ネットワーク障害など)に備えてエラーダイアログなども実装しました。こちらも開発時間に限りがあったため、Firebaseのリアルタイム性を利用して作成しました。(画像の初期画面は一つ前のデザイン案です)

スクリーンショット 2019-11-30 22.31.18

画面間の繊維について
CONNECTでは、映像を扱うインスタレーション作品のため、見栄えが大切となっているため、デザインを重視したアプリケーションを作成しなければなりませんでした。
以下の画像のように、画面が切り替わる際には横にスライドするようなデザインになっています。

スクリーンショット 2019-11-30 22.37.58

UIKitでは、このような繊維方法はデフォルトでは用意されて無いため、UIViewControllerAnimatedTransitioningを用いて自前でViewController間のアニメーションを実装しました。(あまり知見が無く、苦労しました)
また、CONNECT 予約受付システムというタイトル部分については、画面に固定をしたいという要望があったため、NavigationBarの高さを白の領域の少し上まで下げ、ViewControllerを切り替えつつもタイトルを固定しました。

データ管理について
メールアドレスや名前をDBに送信するまで、データを一時的に保存するために以下のようなシングルトンを用いました。1グループの使用後、初期画面に遷移する際にデータを初期化しています。
画面遷移の際に値の受け渡しでも良かったのですが、スッキリするためシン
グルトンを採用しました。

class DataManager: NSObject {
   var name: String?
   var email: String?
   var time: String?
   var reserveTime: ReserveTime?
   var peopleCount = 0
   var child: String?
   
   static let shared: DataManager = DataManager()
   private override init() {}
}

受付アプリのアニメーション
受付アプリの待機中のモーションについてはLottie-iosを使用しました。
Lottieとは、AfterEffectsで作成したモーションをjson形式でクライアントに読み込んで、アニメーションを作成できるライブラリです。
圧倒的に軽量、かつアニメーションをコードから弄れたりするため、非常に使い勝手が良いです。
幸いにも(というかメインコンテンツでガッツリ使用していますが)AfterEffectsを扱える板谷がいたため、アニメーションに関しては特に難なく実装することができました。

メール送信について
Swiftでアプリ開発をする際には、最終的に主にリリースすることが多いと感じています。ユーザに通知せずにバックグラウンドでメールを送信するコードを必要とするアプリケーションは数少なく、ライブラリも数、知見共にあまりありませんでした。
開発時間も限られていたため、SMTPクライアントをアプリ内で動かすよりも、外部にメールだけを送信するAPIサーバーを立ち上げたほうが時間的なコスト削減になると感じたため、POSTリクエストを飛ばすことでお客様のメールにチケットURLを送付する実装をしました。

全体的に感じた点について
今回のアプリケーション開発は、稼働が可能なiOSエンジニアも一人であったり、期間も短いため臨機応変にコーディングする必要がありました。そのためハードコーディングになっている部分も多々ありますが、一回のみのイベント等で使用するアプリケーションでは見た目が綺麗に動くアプリケーションをどれだけ早く実装するかに焦点を当てて開発する必要性を感じました。普段はなかなかしない経験ですが、一人でしっかりと動くアプリケーションを作成した達成感はかなりありました。貴重な経験でした。

QRサイトについて

以下の環境で開発をしております。

python3.7
Flask 1.0.2
html/css

なぜflaskなのか
昨今webフレームワークは大量にあります。そこでなぜFlaskを選択したかという理由は、iOS開発と同じようにリソースがだいぶ限られている為です。
新しい技術を取得するより利用したことのあるFlaskを使ったほうが開発コストがかなり低いと感じたためです。

チケット表示について
予約段階でお客様に送信されているチケットのURLは、
https://tickets.connect.senseart.jp/tickets?id=XXXXXXXXXXXX
(すでにサーバーはダウンしています。)の形式で、XXXXXXXXXXXXがランダムに生成されたチケットIDになっています。
このWEBアプリの構造としては至ってシンプルで、URLに含まれるチケットIDをデーターベースと照合して、画面にQRやその他の情報を表示させる仕組みです。

振り返り
当時は全く時間と技術もなかったため、画像の最適化などをせずにデプロイしていました。もう少しユーザに配慮したウェブサイトにするべきだったと感じます。

ゲート用RaspBerryPiの実装について

以下の環境で開発をしております。

python3.7
RaspBerryPi 3 model B+

読み取りには以下のQRリーダーを使用しました。
当初は、カメラでQRの認識を予定しましたが、精度がかなり悪く、QRリーダーを用いたほうがユーザの体験が向上すると考えたからです。
https://www.amazon.co.jp/gp/product/B076356VMG/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

仕組み
QRコードで読み取られた文字列から、DBと照合してチケットが未使用の場合、ゲートに開閉信号を送ります。ゲートとの通信にはシリアル通信を用いています。

基本的な動作はこれだけですが、DBとの通信に2,3秒程度かかったためゲートで2,3秒待機することはかなりストレスを感じました。そこで、systemctlを用いてデーモン化したキャッシュプログラムを書き、3秒に1回ほど、最新のDBをフェッチして応答速度を実質0秒にすることができました(ファイルの書き込み時にかなり負担がかかってるので、あまり方法とは言えません)。

また、内部でデーモン化したサーバーを動かしており、詳細は割愛しますが、入場ゲート用の認証の可否を表示するディスプレーとも通信を行っております。

オリジナル音楽配信システム

スクリーンショット 2019-11-29 18.02.12

シリアルカードを購入し、コードを入力することでCONNECTオリジナルの音楽をお楽しみいただくためのシステムを開発しました。
シリアルコードの認証の仕組みにはfirebase cloud functionを用いました、データベースと参照をして、アクセス用のtokenを返すようにし、ある程度の不正アクセスを防止します(シリアルコード制にしているため、一定の不正は取り除くことができない点やユーザの個人情報と結びついてない点、から不正な視聴を完全に防止することは不可能だと判断したため、簡易的なtokenとしました)。

なにか今回のシステムに関して質問点等ございましたら、senseのTwitter、メールなどなどどこでも良いので質問してください!
最後までお読みいただきありがとうございました!

この記事が気に入ったらサポートをしてみませんか?