THETA API v2 をいじった時につまづいたり気づいたり試した点１６－２＝１４のこと ＋愚痴

(みなさん興味の沸く記事を投稿している中、文字だけのものすごい地味な内容の投稿となってしまいちょっと恥ずかしいです。)
記事の大半が、静止画撮影モードに関するものになってしまいました。動画撮影モードに関するAPIはそれほど複雑なことがないため取り上げるほどの気付きがなかったというのが正直なところです。
APIをいじる方に(特にこれからいじり始める方に)リファレンスの補足になれば幸いです。

###はじめに
* リファレンスでは、getOptionsコマンドでプロパティ名+"Support"で取得できる値一式のことを"サポート仕様"と呼んでいます。値一式に対してはそのまま"サポート仕様"と呼びますが、値自体のことを"サポート仕様の値"だとなんか違和感があるので文中ではちょっと省略して"サポート値"と呼ぶことにします。
* 露出プログラム関連のものがちょっと長くなったため、露出補正関連プロパティとはどれなのかを予備知識として覚えていただいてから読んでいただくと少しは読みやすくなるかなと思います。露出プログラム関連のプロパティは以下の５つがあります。

>
1. シャッタースピード(shutterSpeed)
2. ISO感度(iso)
3. ホワイトバランス(whiteBalance)
4. 露出補正(EV)(exposureCompensation)
5. 画像加工フィルター(_filter)(公式アプリでは"Option Setting"となっています)

* 露出プログラムの各プログラム名ですが、リファレンスでは"マニュアルプログラム"、"ノーマルプログラム"、"シャッター優先プログラム"、"ISO優先プログラム"となっていますが、公式アプリでこれらに当たるものが"マニュアル"、"オート"、"シャッター優先"、"ISO優先"となっています。感覚的に公式アプリで使用されている名称のほうがわかりやすいと思いますので、各プログラム名は"マニュアル"、"オート"、"シャッター優先"、"ISO優先"を使用することにします。
また、露出プログラム関連の各プロパティ名は公式アプリですと英語表記(略語)を使用しているため、各プロパティ名のほうは上記の日本語(カタカナ)の名称を使用することにします。

#１．電源入れ直すと露出プログラムおよび関連するプロパティがリセットされる
これはAPIというよりTHETA S自体の仕様でしょうね。
電源を入れなおすと、

* 露出プログラム："オート"
* シャッタースピード：0
* ISO感度：0
* ホワイトバランス：'auto'
* 露出補正(EV)：0
* 画像加工フィルター：'off'

にリセットされます(ちなみに、電源切るとGPSの情報もクリアされます)。

#２．露出プログラム関連プロパティのサポート仕様を取得すると、返す値は露出プログラムによって変わる
これ、固定的にサポートする値すべてを返すものと思ってました。現在の露出プログラムによって返す値が変わるのですね。
**露出プログラムによって返す値が変わることをリファレンスに書いてよ！**

```js
/*
各露出プログラムのときに
optionNames: [
  'shutterSpeedSupport', 
  'isoSupport', 
  'whiteBalanceSupport', 
  'exposureCompensationSupport', 
  '_filterSupport'
];
でgetOptionsコマンドを実行。
*/

// "マニュアル"のときのレスポンス
{
  "shutterSpeedSupport": [0.00015625, 0.0002, 0.00025, 0.0003125, 0.0004, 0.0005, 0.000625, 0.0008, 0.001, 0.00125, 0.0015625, 0.002, 0.0025, 0.003125, 0.004, 0.005, 0.00625, 0.008, 0.01, 0.0125, 0.01666666, 0.02, 0.025, 0.03333333, 0.04, 0.05, 0.06666666, 0.07692307, 0.1, 0.125, 0.16666666, 0.2, 0.25, 0.33333333, 0.4, 0.5, 0.625, 0.76923076, 1, 1.3, 1.6, 2, 2.5, 3.2, 4, 5, 6, 8, 10, 13, 15, 20, 25, 30, 60],
  "isoSupport": [100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600],
  "whiteBalanceSupport": ["auto", "daylight", "shade", "cloudy-daylight", "incandescent", "_warmWhiteFluorescent", "_dayLightFluorescent", "_dayWhiteFluorescent", "fluorescent", "_bulbFluorescent"],
  "exposureCompensationSupport": [0],
  "_filterSupport": ["off", "DR Comp", "Noise Reduction"]
};

// "オート"のときのレスポンス
{
  "shutterSpeedSupport": [],
  "isoSupport": [],
  "whiteBalanceSupport": ["auto", "daylight", "shade", "cloudy-daylight", "incandescent", "_warmWhiteFluorescent", "_dayLightFluorescent", "_dayWhiteFluorescent", "fluorescent", "_bulbFluorescent"],
  "exposureCompensationSupport": [-2, -1.7, -1.3, -1, -0.7, -0.3, 0, 0.3, 0.7, 1, 1.3, 1.7, 2],
  "_filterSupport": ["off", "DR Comp", "Noise Reduction"]
};

// "シャッター優先"のときのレスポンス
{
  "shutterSpeedSupport": [0.00015625, 0.0002, 0.00025, 0.0003125, 0.0004, 0.0005, 0.000625, 0.0008, 0.001, 0.00125, 0.0015625, 0.002, 0.0025, 0.003125, 0.004, 0.005, 0.00625, 0.008, 0.01, 0.0125, 0.01666666, 0.02, 0.025, 0.03333333, 0.04, 0.05, 0.06666666, 0.07692307, 0.1, 0.125],
  "isoSupport": [],
  "whiteBalanceSupport": ["auto", "daylight", "shade", "cloudy-daylight", "incandescent", "_warmWhiteFluorescent", "_dayLightFluorescent", "_dayWhiteFluorescent", "fluorescent", "_bulbFluorescent"],
  "exposureCompensationSupport": [-2, -1.7, -1.3, -1, -0.7, -0.3, 0, 0.3, 0.7, 1, 1.3, 1.7, 2],
  "_filterSupport": ["off", "DR Comp", "Noise Reduction"]
};

// "ISO優先"のときのレスポンス
{
  "shutterSpeedSupport": [],
  "isoSupport": [100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600],
  "whiteBalanceSupport": ["auto", "daylight", "shade", "cloudy-daylight", "incandescent", "_warmWhiteFluorescent", "_dayLightFluorescent", "_dayWhiteFluorescent", "fluorescent", "_bulbFluorescent"],
  "exposureCompensationSupport": [-2, -1.7, -1.3, -1, -0.7, -0.3, 0, 0.3, 0.7, 1, 1.3, 1.7, 2],
  "_filterSupport": ["off", "DR Comp", "Noise Reduction"]
};
```
返された値が現在の露出プログラムにおいて設定できる各プロパティの値となります。
例えばシャッタースピードですが"マニュアル"と"シャッター優先"以外は要素数0の配列が返ってきます。また"マニュアル"と"シャッター優先"とでは返す値(要素数)が違います。"マニュアル"ではすべての値が返ってきますが、"シャッター優先"では、0.16666666(1/6)以上の値は設定できないため、0.125(1/8)以下の値までが返ってきます。
この返ってきた値以外を各プロパティに設定しようとするとinvalidParameterValueエラーが返ってきます。
ただし、画像加工フィルターなのですが、公式アプリでは"オート"のときのみ設定できるプロパティです。返されるサポート仕様が示すように、すべての露出プログラムにおいてエラーが返らず設定することができます。リファレンスには"\_filterが有効の場合、露出プログラム(exposureProgram)より優先される"と書かれているようにたぶん_filterが'off'以外に設定された場合は、_filterの設定が優先されるのでしょう。
ただ、これがちょっと厄介な問題を起こします。これについては次に述べます。

#３．露出プログラムの変更ができなくなる
画像加工フィルターは、前述のようにすべての露出プログラムのときに変更できてしまうのですが、これを'off'以外の値に変更したとき、そのままだと"オート"以外の露出プログラムに変更することができなくなってしまいます(invalidParameterValueエラー)。もし、'off'以外に設定していた場合は、いったん'off'に設定しなおせば、露出プログラムを変更することができます。
気になって調べてみると、なんと**\_filterに'off'以外を設定すると自動的に露出プログラムが"オート"になっていました。**なのでシャッタースピードやISOやホワイトバランスも0(Auto)または'auto'になります。
でも、逆に考えると\_filter設定するだけで"オート"なるというショートカット的な使い道としてはありかもですね。
**\_filterに'off'以外を設定すると露出プログラムが自動的に切り替わることをリファレンスに書いてよ！！**

#４．複数のプロパティを１回のコマンドで設定するとき、ちゃんと優先順位の高いほうから処理を行っているっぽい？
引き続き露出プログラムネタですけど、例えば現在の露出プログラムが"オート"だとします。これから"マニュアル"に変更およびシャッタースピードの設定を行いたいとしたとき、素直に考えると"オート"のままだとシャッタースピードの設定が行えませんので、"マニュアル"に変更した後、シャッタースピードの設定を行うという２回のコマンドの実行が必要と予想します。
setOptionsコマンドは１回で複数のプロパティの設定も可能ですので、これを一回のコマンド実行でプログラムの変更とシャッタースピードの設定を同時に行うとどうなるか。実験してみると、エラーが返らずちゃんとプログラムの変更およびシャッタースピードの設定することができました。渡すオブジェクトのキーの順番を入れ替えても同じく問題なく設定できました。
ただし、ここで１つの陳腐な懸念点が思いつきます。単純にアルファベット順でソートして実行しているのではないかと。だから画像加工フィルター(プロパティ名は"\_filter")はどの露出プログラムにおいても設定できちゃうのではと。
ということで、今度は"マニュアル"から"オート"に変更と"マニュアル"では設定できない露出補正(EV)の設定を１回のコマンド実行でやってみます。露出補正(EV)のプロパティ名は"exposureCompensation"で、露出プログラムのプロパティ名は"exposureProgram"ですので、アルファベット順にソートすると露出補正(EV)が前にきます。懸念点通りですとエラーが返ってきますが、今回の結果もエラーが返らず変更および設定が行えました。
このことにより、ちゃんと優先順位の高いほうから処理してるっぽい？。(優先順位とかではなく別な理由かもしれませんが)
なので、前述の画像加工フィルターの問題に関しても、１回のコマンドで{exposureProgram:1か4か9,\_filter:'off'}を渡して実行することで露出プログラムを変更することができます。
**追記(2015/12/12)**１回コマンド実行で撮影モードとファイルフォーマットの同時変更はできませんでした。

#５．サポート値以外は受け付けない
例えばシャッタースピードで1/6を設定するとします。サポート値では0.16666666ですが、1/6を素直に計算した値は言語によって差異があると思いますが例えばJSだと0.16666666666666666になります。この値をそのまま設定しようとするとinvalidParameterValueエラーが返ってきました。もしこれができるのであれば、母数を変えて計算するだけでよくなりプログラミングが楽なるのではと期待したんですけどダメでした。

#６．~~一部のサポート仕様を取得しようとするとエラーとなる~~(2015/12/13削除)
~~リファレンスには書かれていませんが、以下のサポート名でサポート仕様を取得しようとするとinvalidParameterValueエラーが返ってきます。エラーとはせずに、nullや空文字といったもので返してほしいと思うんですけどね。
**一部のサポート仕様は取得できない(エラーが返る)ことをリファレンスに書いてよ！！！**(これだいぶ前にRICOHにリクエスト投げたんですけど完全に無視されてますね)~~

|~~取得しようとするとinvalidParameterValueとなるサポート仕様名~~|
|-------------------|
|~~dateTimeZoneSupport~~|
|~~gpsInfoSupport~~|
|~~remainingPicturesSupport~~|
|~~remainingSpaceSupport~~|
|~~_remainingVideosSupport~~|
|~~totalSpaceSupport~~|
|~~_wlanChannelSupport~~|
コメントをいただき、[Optionsのoverview](https://developers.theta360.com/ja/docs/v2/api_reference/options/)というページが追加されているのに気づきました。

#７．コマンドのパラメーターの値に長い文字列(データ)やnullを設定してコマンドを実行するとTHETA S本体が落ちる
ある程度の長さまではinvalidParameterValueエラーが返ってくるのですが、一定の長さを超えたものをコマンドのパラメーターの値に設定して実行するとTHETA S本体が落ちます。落ちるだけで再起動可能です。まあ、まずそもそも長い文字列(データ)を設定すること自体あり得ないですけどね。ですので、具体的にどういった条件下で落ちるのかなど突っ込んだ調査まではしてません。
また、パラメーターの値にnullを設定してコマンドを実行しても同様にTHETA S本体が落ちます。
長い文字列で落ちるのは解せるんですが、nullで落ちるのはちょと解せないですね。

#８．~~listImagesコマンドをincludeThumb:trueにして実行するとエントリーが１つしか返ってこない~~
~~リファレンス読む限りだとそんなことは一切かかれていないのですけどね。このことをRICOHに問い合わせてみたのですが、これ仕様なんですって♪あははｗ。この回答が返ってきたときちょっとどころではない怒りを覚えましたよ、ええ。
なぜなら、リファレンスのResultsサンプルはご丁寧にもサムネイル付きの複数のエントリーものが記述されているのですから。だったら、リファレンスを修正しろよって返事をしたのですが一向に修正されません(怒)。~~ 
12/5時点では修正されていませんでしたが、12/6に見たら修正されてました。(なんというタイミングのよさｗ)
ちなみに、[これ](http://webcache.googleusercontent.com/search?q=cache:SDlmBXrj9TsJ:https://developers.theta360.com/ja/docs/v2/api_reference/commands/camera.list_images.html+&cd=1&hl=ja&ct=clnk&gl=jp)が修正前のもの。下は問い合わせたときのツイート(スペルミスは無視してください)。
<blockquote class="twitter-tweet" lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/gtk2k">@gtk2k</a> RICHOに問い合わせたら仕様なんだそうだ。&#10;いやだから、そういった仕様部分をリファレンスに書けよ。</p>&mdash; gtk2k (@gtk2k) <a href="https://twitter.com/gtk2k/status/659353636955250688">2015, 10月 28</a></blockquote>

#９．レスポンスヘッダにAccess-Control-Allow-Originがない
これ非常に残念です。大事なことなのでもう一度言います。**これ非常に残念です！！！！！**
せっかくHTTPプロトコルになったのに、これがないことでWebアプリからAPIにアクセスすることができません(同じドメイン環境下ならアクセスできますが)。一応、RICOHにはリクエストは投げたんですけど、期待できません。

#１０．GPS情報を設定するとき緯度(lat),経度(lng)両方同時に設定しないとダメと返してくれる
これはちゃんとチェックしてくれます。緯度と経度以外の位置情報取得時刻(dateTimeZone)や高度(_altitude)、測地基準(_datum)はは設定しなくても大丈夫ですが、緯度だけ設定しようとしたり、経度だけ設定しようとしたりするとinvalidParameterValueエラーを返してくれます。緯度経度両方同時に設定すればエラー返らず設定できます。

#１１．GPS情報を電源を切らずにコマンドでクリアするには？
今度は逆にどうすればGPS情報をコマンドでクリアできるの？というと、gpsInfoに緯度(lat)と経度(lng)の値を65535に設定してsetOptionsコマンドを実行すればGPS情報がクリアされます。

```js:GPS情報をクリアするパラメーター
{
  "name": "camera.setOptions",
  "parameters": { 
    "sessionId": "SID_0010",
    "options": {
      "gpsInfo": {
        "lat": 65535,
        "lng": 65535
      }
    }
  }
}
```

#１２．複数同時コネクション可能
１つだけではなく複数のコネクションを同時にできるんですね。１つしか接続できないとこの間まで思い込んでいました。なので、ライブプレビュー用とコマンド用の２つのコネクションを生成し、公式アプリのようにライブプレビューのストリームを表示しながら、ISO感度やホワイトバランスを変更するということが簡単にできます。

#１３．接続切ってもセッション自体は有効
接続を切るとセッションもそこで終了かと思いきや、電源を切ったりタイムアウトしない限り、そのセッションは有効で、再接続したら切断前のセッションIDを使ってAPIを使用することができます。また、前述の複数同時接続においても、すべての接続で同一セッションを使用できます。まあ、次に述べますが、セッションを何回更新しても問題ないですけどね。

#１４．listAllコマンドでdetailをfalseにした時のdateTimeとdetailをtrueにした時のdateTimeZoneの値に若干のずれがある
同じファイルなのですがdetailをfalseにした時のdateTimeとdetailをtrueにした時のdateTimeZoneを取得してみたら
>
dateTime: "2015:12:08 12:25:14"
dateTimeZone: "2015:12:08 12:25:09+09:00"

といった感じで約5秒ぐらいずれています。まあ、気にするほどのずれではないですけどね。

#１５．セッションIDは無限ループ？
とてつもなくしょーもないことですが、APIを触った方ならご存知の通り、セッションIDは"SID_0001"といった感じになっており、新規にセッションを開始すると新しいセッションのIDは４桁の数字がカウントアップしたもの(例:"SID_0002" "SID_0003")という仕組みになっています。
そこで、セッションを生成し続ける(startSessionコマンド)とどうなるか実験してみました。すると、"SID_9999"の次は"SID_0001"となり("SID_0000"となるのではとちょっと期待したんですがｗ)、以降ずっとループすると予想されます。なので、セッションはいくら生成しても問題ないでしょう。まあ、そもそも１万回もセッションを生成することはまずないでしょうけど。

#１６．フォルダ名とファイル名**(2015/12/13追加)**
フォルダ名やファイル名からどのようになるかは想像できるのですが、DCF2.0準拠というのがちょっと気になりました。DCF2.0ではフォルダが違えばと同名のファイルを置くことができるとなっているため、ファイル名だけでは一意に決められません。
なので、実際どのようなフォルダ名やファイル名になるかを実験してみました。
THATA S本体のストレージに外部からフォルダを作成したりファイルを追加することができないため、実験するには撮り続けなければりませんが、インターバル撮影が役に立ちました。開始して放置プレイです。(ただ、温度異常でおちることがしばしば)
結果は、最初のフォルダ名は"100RICOH"でその配下のファイル名は"R001"から始まるファイル名となり、下４桁が9999になると、次のフォルダ"101RICOH"が生成されました。このフォルダ配下のファイル名は"R002"から始まるものになりました。
あと、THATA S本体のストレージに外部から書き込むことはできませんが、フォルダやファイルを削除することができます。試しにフォルダを削除してすべてのファイルを削除した後に撮影してみると、カウンターが保持されているらしく"100RICOH"ではなく"101RICOH"が生成され、またファイル名も"R0022415.JPG"といった感じで前回のカウントからのもの作成されました。
これにより、ファイル名だけでも一意にファイルを指定することができることがわかりました。

100RICOH
&nbsp;└┬ R0010001.JPG
&nbsp;&nbsp;&nbsp;├ R0010002.JPG
&nbsp;&nbsp;&nbsp;├ R0010003.JPG
&nbsp;&nbsp;&nbsp;├ ～～
&nbsp;&nbsp;&nbsp;└ R0019999.JPG

101RICOH
&nbsp;└┬ R0020001.JPG
&nbsp;&nbsp;&nbsp;├ R0020002.JPG
&nbsp;&nbsp;&nbsp;├ R0020003.JPG
&nbsp;&nbsp;&nbsp;├ ～～

#余談
公式リファレンスは結構重要なところが欠けているもんだから、余計な時間を食わせていただきましたよ、ええ。

今では、ほとんどがフィードバッグ専用のサイトを設けてそこでフィードバッグを受け付けたり、フォーラムなどでフィードバッグや質問を受け付けているなか、RICOHにおいてはネットでフィードバッグや質問を行う方法として、問い合わせフォームから行う方法しかなく、しかも、問い合わせるには個人情報を登録しないとできないというありさまで、なんとも時代遅れなもの。気楽に質問なんてできません。せっかくフォーラムページ作ってるのだからそこにフィードバッグや質問を受け付けるスレッドを作成してくださいよ。