用語
- 機器:HTTP/HTTPSな環境から操作する機器
- 機器種別:機器の種類。例、エアコン、照明、etc。あるいはエアコンもメーカによって異なる機種種別として扱う必要があるかもしれません。
要件
IoTの理想「標準的なIFでIPネットワークに繋がるいろんな機器を組み合わせて遊ぼう!」
— ぎゃばんV8!V8! 怒りのデスロード (@ledsun) 2017年3月2日
IoTの現実「別々に設計された、IPではない個別のIFでつながっている、IPにつながっていたとしてもRESTfulとは限らない、正直用途不明な、いろんな機器のIFをすり合わせます。」
現在のIoTでは機器種別によって、ネットワークを介した操作方法が異なります。 機器種別によっては直接HTTP/HTTPSの世界と接続できないことがあります。
例えば6LoWPANという規格でつながっているかもしれません。 IoT規格 6LoWPANとは? | IoT
IoT機器を制御するWebアプリケーションを作るには、HTTP/HTTPSの世界につなぐゲートウェイが必要です。 RESTful APIでIoT機器を制御できれば、Webアプリケーションエンジニアにアプリケーション作成環境を提供できるでしょう。
モデリング
IoT的な話でな。機器と通信するclientクラスと機器の情報を持つprofile(機器の特有情報をもつsub profileもあるよ)を機器モデルに持たせて、ロジックをなるべくモデルに詰め込むと割と上手く行った。DBに入れるのはprofileでモデルではない。
— ぎゃばんV8!V8! 怒りのデスロード (@ledsun) 2017年4月27日
IoTゲートウェイでは、原則として、機器種別に応じて変わる情報をロジックで実装します。 機器の設定変更に応じて変える情報はDBに保持します。 大きく次の3つのモデルに分けます。
- Deviceクラス
- Profileクラス
- Clientクラス
これらのクラスはWebMVCの分類では、いずれもModelです。 ここではViewやControllerに関する設計は扱いません。
Device
Deviceは機器操作ロジックを担当します。
操作したい機器と通信相手が1:1とは限りません。 1つの通信相手が複数の機器を管理していることがあります。 この関係性は静的な情報です。ロジックとして実装します。
機器がJSONでのリクエストを受け入れない場合は、JSON以外の異なるフォーマットに変換する必要があります。 ゲートウェイのRESTful APIは、人間が読めるパラメータが望ましいです。 機器が16進数文字列を要求する場合、変換して送る必要があります。
1つのRESTful APIリクエストに対して、機器に複数のリクエストが送る必要がある場合、 それらのシーケンスはここで実装します。
DeviceはProfileとClientを持ち(に依存し)ます。
Profile
Profileクラスは機器の情報を持ちます。 代表的なものに次があります。
- 名前
- 機器種別
- 位置情報
- 接続情報
ロジックとしては、検索ロジックを担当します。 ProfileクラスはDBのレコードと対応しています。 Active Recordパターンを使うのに適しています。 Ruby on RailsであればActiveRecordやApplicationRecordを継承したクラスとして実装します。
機器種別ごとの拡張が必要な場合は機種別のSubProfileクラスを作ります。 例えば、機器種別ごとに接続方式が異なる場合は次のように情報を持ち分けます。
- Profile
- 名前
- 位置情報
- 機種種別
- SubProfile
- 接続情報
ProfileクラスとSubProfileクラスには継承関係は持たせません。 DeviceがProfileインスタンスとSubProfileインスタンスを持ち、適宜使い分けます。
想定外の新しい機種種別を追加した際に、Proflieには影響を与えたくありません。 1:1関係のテーブルに分けます。
関連付けにはidを使います。 外部との接続性を重視した場合は、idにUcodeを使うかもしれません。 Ucode | IoT
Client
Clientは機器との通信を担当します。 原則として状態は持ちません。 通信状態は持ちますが、通常はHTTPClientなどの別のクラスに移譲しているでしょう。
機器がHTTP/HTTPSで通信できれば、特に難しいことはありません。 リクエスト送信先を整形し、リクエストボディを整形し、リクエストを投げるだけです。 ロジックと言っても、せいぜい通信エラーを例外で抽象化するぐらいです。
Clientを別クラスに分ける最大の効果はユニットテストの書きやすさにあります。 Deviceのテストコードを書く際に、ClientのインターフェースにあわせたMockに置き換えることができます。 Deviceは比較的複雑なロジックを持っているので、ユニットテストで品質を確保します。
IoTではエンドツーエンド試験環境を作るために、機器を用意する必要があります。 機器とゲートウェイの製造が並行している場合は、試験が開発期限ギリギリまで行えないことがあります。 事前にユニットテストでテストしておきたいところです
アプリケーションレベルの分割戦術
エアコンと言ってもメーカごとに接続方法や操作方法が異なります。
ここで扱ったHTTP/HTTPS世界とのゲートウェイの他にもう1つ エアコンを抽象化するゲートウェイを用意すると、分業しやすくなるでしょう。