開発者登録
RICHO THETA SCは、外部からのアクセスが可能となっており、各種APIが公開されているとのこと。WiFiで接続して、スマホなどからアクセスすることで、シャッターを切ったりするアプリを、自分で作れるようになる。 まあ、スマホアプリを作るスキルはないのだが、開発者登録はしてみようと思う。
開発者になるには、登録が必要な様子。開発者サイトから登録を行う。緑の始めるボタンを押す。

アカウント作成は、facebookかtwitterアカウントで行うようだ。 では、facebookで登録してみよう。

facebookのアカウントでログインすると、登録情報が送信され、開発者アカウントの作成が開始される。 といっても名前だけ拾われていったようだ。変更も可能なのだが、わかりにくくなるのでそのまま登録を押す。

これで登録完了。ログインした状態だと、右上にアカウント名が表示される。ログアウトするときはすぐ右のボタンだ。

何が出来るのかというと、以下のことが出来るらしい。

API&SDK
では、API&SDKをクリックして開発者サイトに行ってみよう。

使用することになるのは、APIv2となる。これが最新のAPIで、THETA S以降はこちらが推奨。SCはもちろんOK。 V2だとgoogleのOpen Spherical Camera API準拠だそうなのだが、まあこれを知らないのでどうでもよい。それよりも、v2だとhttpベースらしく、POSTでやり取りが出来て、データはJSON渡しらしい。最近っぽい。

あと、下の方にはSDKが準備されている。

iOSやAndroidアプリ開発のテンプレートがある様子。せっかくなのでダウンロードしてみよう。 もしかすると奇跡が起きて、スマホアプリを作ることになるかも。

v2版をダウンロードして、一応クイックスタートを見て見るが、どうもクイックにスタートはできそうに無い。
では、v2のAPI Referenceを見てみよう。雰囲気的には、THETAがWiFiでつなぐと192.168.1.1なので、 80版ポートにPOSTしてやると、色々出来る様子。v2のGetting Startedを見ると、具体的な手順が載っていた。

Getting Startedを見ると、これに記載のある1~6の手順で撮影から写真の取得までが出来る様子。 スマホの公式THETA Sアプリもこれで動作している様子で、なんかアプリが作れそうな気分になってくる。

ラズベリーパイ
ハックといえばラズベリーパイだ(しらんけど)。というわけでもないが、いろいろやるには便利な機器。 こいつを使ってシータにアクセスしてみよう。
というのも、PCからシータへのアクセスは少し面倒で、WiFiで繋ぐ必要があるのだが、 PCには有線LANしかなく、無線LANを動かす必要がある。 ラズベリーパイなら、有線無線LANをよく使うので、両方使用させればうまくいくはずだ。 つまりPC->有線LAN->ラズベリーパイ->無線LAN->シータと言った具合。
では、ラズベリーパイに繋いで、まずはラズパイとシータを接続だ。 シータを起動して無線LANを動かしておく。誰もつながっていないと無線LANマークが点滅する。

この状態で、ラズベリーパイの無線LANを接続させる。GUIが楽なので、VNCで繋いで、右上の無線LANの矢印をクリックすると、近くのアクセスポイントが表示されるので、 この中からTHETA~.OSCのアクセスポイントを選ぶ。

すると、パスコードを聞いてくるので、シータの裏面にある製造番号らしきものの、数字部分を入力してやる。

これで、接続要求に行く。すぐに接続してマークがWiFiになり、チェックボックスが付けば接続完了だ。

では、ここからラズベリーパイよりシータへのアクセスを開始する。 まずはネットワークの状態確認
無線LANとして、192.168.1.5が当てられたようだ。ではpingしてみよう。
シータと思われる192.168.1.1にpingしてみると応答があった。うまくシータネットワーク?につながっていて、 シータもきちんと見えているようだ。
ちなみに、スマホ(Android)側でシータにアプリで接続している状態だと、ラズパイ側からの接続ができなかった。また、逆にラズパイで接続中にスマホアプリで接続を試すと、繋がらなかった。シータのWiFiは一つしか受け付けない様子。
あと、シータのオートパワーオフを設定していたので、まごまごしていると、シータの通信が切れてしまう。 オートパワーオフは切っておくことにした。
電源が入っているときのLEDは結構明るく目立つので、電源入れっぱなしは気づきやすいし、三脚などに設置しての撮影時に勝手に切れられると、また電源投入に行くのが大変。電源はボタン押せばすぐに立ち上がるので、 こまめにオフすれば大丈夫そうだ。
では、API v2 Referenceに従って、 アクセスしてみよう。まずは、 info を取得してみる。infoはhttpにGETアクセスすると、レスポンスとして、各種本体の情報を返してくれるらしい。 シータの80番ポートにアクセスすれば良いので、curlコマンドでつついてみよう。

curl http://192.168.1.1:80/osc/info
{
"api": [
"/osc/info",
"/osc/state",
"/osc/checkForUpdates",
"/osc/commands/execute",
"/osc/commands/status"
],
"apiLevel": [
1,
2
],
"endpoints": {
"httpPort": 80,
"httpUpdatesPort": 80
},
"firmwareVersion": "01.01",
"gps": false,
"gyro": false,
"manufacturer": "RICOH",
"model": "RICOH THETA SC",
"serialNumber": "********",
"supportUrl": "https://theta360.com/en/support/",
"uptime": 727
}
すこし戻り値は見やすいように整形したが、JSON形式でレスポンスが戻ってきた。シリアルはマスクしてある。 サンプル通り値が返ってきたので、よかった。infoはあまり見るべきところは少ない。ファームバージョン調べるくらいか。
では、同様にstate についてもやってみよう。こちらはPOSTしなきゃなので、「-X POST」を付けて実行する。
curl -X POST http://192.168.1.1:80/osc/state
{
"fingerprint": "FIG_0003",
"state": {
"_apiVersion": 1,
"_batteryState": "disconnect",
"_captureStatus": "idle",
"_latestFileUri": "",
"_recordableTime": 0,
"_recordedTime": 0,
"batteryLevel": 1.0,
"sessionId": "SID_0001",
"storageChanged": false
}
}
ふむふむ、よくわからん。どうやら_captureStatusあたりが、撮影状況を表すようで、撮影実施後はこのあたりを見て、 シータが落ち着いたかどうか判定するようだ。
では、Getting Started に従い、ひととおりの静止画撮影からファイル取得までにチャレンジしてみよう。 最初は「APIバージョンの指定」だ。説明を読むと、最初はV2.0モードで(確かにさっき_apiVersionが1だった)動作していて、 これをV2.1に変えるらしい。
curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.startSession"}'
{
"name": "camera.startSession",
"results": {
"sessionId": "SID_0003",
"timeout": 180
},
"state": "done"
}
「SID_0003」というセッションIDが取得できた。このままもう一回コマンドを飛ばせば、SID_0004となった。勝手にインクリメントしたIDを発行しているようだ。
セッションIDを取得したら、このIDを使ってAPIバージョンの指定を行う。
curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.setOptions","parameters": {"sessionId": "SID_0004","options": {"clientVersion": 2}}}'
{
"name": "camera.setOptions",
"state": "done"
}
うまくいった雰囲気のレスポンスが返ってきたので、大丈夫だろう。では、stateをみて、ちゃんと変化したか確認する。
curl -X POST http://192.168.1.1:80/osc/state
{
"fingerprint": "FIG_0003",
"state": {
"_apiVersion": 2,
"_batteryState": "disconnect",
"_captureStatus": "idle",
"_latestFileUrl": "",
"_recordableTime": 0,
"_recordedTime": 0,
"batteryLevel": 1.0,
"storageUri": "http://192.168.1.1/files/abcde/"
}
}
_apiVersionが1から2に変わっている。また、storageUriに何かしら値が入っている。順調そうだ。ではカメラのイメージフォーマット情報の取得を行う。
curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.getOptions","parameters": {"optionNames": ["fileFormat","fileFormatSupport"]}}'
{
"name": "camera.getOptions",
"results": {
"options": {
"fileFormat": {
"height": 2688,
"type": "jpeg",
"width": 5376
},
"fileFormatSupport": [
{
"height": 2688,
"type": "jpeg",
"width": 5376
},
{
"height": 1024,
"type": "jpeg",
"width": 2048
}
]
}
},
"state": "done"
}
現在設定の画像サイズなどがレスポンスで返ってきた。Getting Startedのサンプルでは、画像サイズの変更手順があるが、 現在のサイズでよいので、この手順は省略する。
次にとうとう静止画撮影を行う。つまりシャッターを押す操作となる。
curl -X POST http://192.168.1.1:80/osc/commands/execute -d '{"name": "camera.takePicture"}'
{
"id": "1",
"name": "camera.takePicture",
"progress": {
"completion": 0.0
},
"state": "inProgress"
}
キュイ~ッポといった変な音とともに撮影された。撮影と、その保存処理が完了したかは、CheckForUpdatesの状態IDを見るらしい。よくわからないが、やってみよう。
curl -X POST http://192.168.1.1:80/osc/checkForUpdates -d '{"stateFingerprint": "FIG_0003"}'
{
"stateFingerprint": "FIG_0005",
"throttleTimeout": 1
}
stateFingerprintが、最初のFIG_0003から、FIG_0005に変わっているので、これが作業終了した合図らしい。 途中何かの操作で、FIG_0004に変わったアクションがあった様子。まあ、stateFingerprint値が変化したら、完了ということのようだ。
では、撮影したファイルを取り出す操作を行う。stateすると、直前撮影のファイルの場所が返ってくるので、実行する
curl -X POST http://192.168.1.1:80/osc/state
{
"fingerprint": "FIG_0005",
"state": {
"_apiVersion": 2,
"_batteryState": "disconnect",
"_captureStatus": "idle",
"_latestFileUrl": "http://192.168.1.1/files/abcde/100RICOH/R0010018.JPG",
"_recordableTime": 0,
"_recordedTime": 0,
"batteryLevel": 0.67,
"storageUri": "http://192.168.1.1/files/abcde/"
}
}
ファイルの在処が判明したらGETコマンドで取得する。バイナリなのでリダイレクトしてファイルに落とす。
curl http://192.168.1.1:80/files/abcde/100RICOH/R0010018.JPG > r0010018.jpg
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4004k 100 4004k 0 0 974k 0 0:00:04 0:00:04 --:--:-- 974k
これで、撮影した画像ファイルをローカルに取得できた。
だいたいの基本操作はわかってきた。シャッターを押すだけならセッション張ってシャッター要求すれば良さそう。 どんな活用をしようかな?