nature cloud apiをswagger codegenで扱おうとして苦労した話


はじめに

Nature RemoのAPIはswaggerで記述されていてswagger.ymlも取得できるので、これならクライアント部分はswagger codegenで作成すれば一発かなと思ったのですが、残念ながらいくつか問題があって一発というわけにはいきませんでした(だいたいは使えましたが)

困ったところ

APIのパスと生成される関数名の問題

生成される関数名はパスの構成要素をcamel capsにしてつなげたものの末尾にHTTPのメソッド名をつける、という規則で生成されるようなのですが、Nature RemoのAPIのパスは全て先頭にバージョン番号をつけて/1/appliancesのようになっているので、生成される関数名が例えば1AppliancesGetとなってしまいました。もちろんPHPは数字で始まる関数名はアウトです。

これは/1の部分をbasePathに移動させることで解決しましたが、codegen側でうまいことやって欲しいところです。単純にgetやpostなどのHTTPのメソッド名を末尾ではなく先頭にすればいいような気もしますが、後にする習慣でもあるのでしょうか。

swagger.ymlと実際のAPIからの返却値の不一致

いくつか定義ファイルと実際の返却値でプロパティの名前が異なっているもの、enumで定義されてない値が返ってくる物がありました。生成されるコードではその辺も機械的に扱われるので値が空になったりエラーになったりします。とりあえず現物合わせでswagger.ymlを修正して対応しました。(本件についてはNature社に報告済みです)

一部の値がうまくデシリアライズされず空になる。

$refで参照されたデータの定義がobjectでもenumでもないケースでうまくデシリアライズされずデータが参照できません。なんとなくcodegen側の問題のような気もしますが適当に改造して対応しました。

おわりに

最終的に出来上がったクライアントがremo-clientで、これを使ってhomekitからhomebridge経由で操作するためのソフトがhttp-thermostat-remoです。

去年はAPIが提供されていなかったのでIRKit互換で使えるという情報を元にとりあえず動かしてましたが、

  • リモコンの赤外線信号を温度毎に1つずつ読んで設定ファイルを作るのが大変
  • nature remoのサーバを通さずに操作するのでRemoアプリに状態が反映しない

という問題があり、これらが解決して快適です。エアコン操作についてはAppleのホームアプリよりRemoのアプリの方が使いやすいのでアプリで操作するときはRemoアプリを使ってますが、homekitに対応させるのは以下のメリットがあります。

  • Siriで音声コントロールできるのがやはり便利
  • 朝にタイマーでエアコンをつけるのに、ホームアプリなら「家にいるときのみ」の条件をつけられるので旅行などの時も安心。