エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

Tesla API を使って Flutter アプリを作ってみた

【マルチデバイスチーム ブログリレー3日目】

イントロダクション

コーヒーと日本酒が大好きなエンジニアリンググループ・マルチデバイスチームの田根です。
昨年飲んだ日本酒で一番美味しかったのは「みむろ杉 純米大吟醸 酒未来」でした。
チーム内では iOS/Android アプリのフロントエンドの開発からバックエンドのサーバーサイドの開発まで行っています。

今回新たに Flutter で実装されている AskDoctors のスマホアプリの開発に参加することになりました。
Swift や Kotlin でのアプリ開発経験はあるのですが、Flutterアプリは初めてということもあり、Flutter/Dart を理解するために趣味と実益を兼ねて Tesla API を使って指定時間に車両の充電を停止する Flutter アプリを作ってみました。
また AskDoctors は一般の患者さんが気軽にお医者さんに相談できるサービスですので、ぜひみなさんもご利用ください。

作成するアプリの内容

プライベートでTesla Model 3 という電気自動車(BEV)に乗っており、充電の管理はTeslaから提供されている公式アプリで行えます。
私の契約している電力会社では午前1時~午前5時の間は充電し放題となっており、午前5時に充電を停止させたいのですがTesla公式アプリには指定した充電容量で止める機能しかありません。 さらに公式アプリでの「充電制限」の下限容量が50 %となっているため、午前1時に充電を始めても午前5時の時点で50%に届かないと見込まれる場合は、わざわざ午前5時に目覚ましをかけて手動で停止していました。 その運用はさすがにつらいので指定した時間に Tesla の充電停止APIを叩いて充電を止めるアプリを作成することにしました。

納車待ちのModel3の様子

Tesla API について

Tesla の車両はAPIを経由して車両の情報の取得や各種設定を行えるようになっています。
Tesla の API は公式に公開されているものはなく、非公式で公開してくれているサイトがあるのでこちらを参考に実装しました。 ちなみに Tesla API で検索するとトップに出てくるサイトの情報は少し古いようです。
認証方式は OAuth 2.0 で実装されています。
Tesla社が公式に公開しているAPIではなく非公式APIなのでもし利用しようと考えている場合は自己責任でご利用ください。

利用したライブラリ

Authentication

認証は OAuth 2.0 なのですが、こちらのドキュメントを見てもらうとわかるようにWebフォームを経由して認証情報を取得しないといけません。
ちょっと実装が面倒だったのと、もしアプリを公開した場合にアプリ上からID/Passwordを入力するのが抵抗があると考えたため refresh token を入力してもらい、 access token を取得する方式にしました。
Tesla の認証トークンを取得するアプリをオープンソースとして公開してくれている人がいたので、セキュリティ的に問題ないことをソースを確認してエミュレータ上で実行して refresh token を取得しました。

API Client

一番有名だと思われるretrofitを使いました。
API Client のインタフェースと Model を作成してflutterコマンドを叩くと自動生成して実装してくれるので楽チンでした。

Timer

タイマー機能は何で実装しようかと悩んだのですが、cronというcronと同じ記述で定期実行することが出来るライブラリがあり、これを使ってみることにしました。
アプリがバックグラウンドの状態で正常に動作するのか心配でしたが問題なく動いているようでした。

Log

バックグラウンド状態で cron が実際に動いて充電停止まで成功したのか確認するためにloggerを使い LogOutput を独自に実装してアプリ上から確認出来るようにしました。

作成したアプリ

認証画面

refresh token を入力して Refresh Token API を叩いて access token を取得しています。

認証画面

充電スケジュール画面

Charge State API を叩いて車両の現在の充電状態と充電スケジュールを表示しています。
最後に edit で停止時間を指定します。
現在のバッテリーレベルが86%で充電制限が90%に設定されていることが確認出来ます。
充電スケジュールは0時半に開始し、1:28に停止するように設定されています。

充電スケジュール設定画面

Cron ログ

1:28にcronが実行され充電の停止に成功したことがわかります。
Command - Charge Stop API を叩いて充電を停止し、その結果を表示しています。

cronのログ

感想

Flutter

  • クロスプラットフォームを簡単に開発出来るのはすごく楽
  • 修正をすぐに確認できるホットリロードがとても便利
  • iOS でも UI はどうしても Android のマテリアルデザイン寄りになってしまう
  • Flutter SDK のバージョンアップによる破壊的変更が多い(古い記事のサンプルコードを貼り付けるとコンパイルが通らないことが多かった)
  • UI の実装が入れ子になって実装するのも読むのもつらい

Dart

  • async/await による非同期処理の実装が楽
  • 行末のセミコロン付けるのすぐ忘れる
  • variable == null という書き方が Swift/Kotlin と比べるとどうしても多くなり、書き方がスマートではない

まとめ

1つのソースコードで iOS/Android アプリの両方を簡単に作れるというのはすごくいいと感じました。
ただどうしても Google製ということもあり、iOS端末でも Android っぽい UX になるのは違和感がありました。
簡単なアプリを開発するなら iOS/Android で別々に開発する必要がなくなるので大きな工数削減が実現出来そうです。大規模アプリの場合はUXを各OSに特化して実装できるので今まで通り iOS/Android を別々に開発した方が良いものが実現できると考えます。 最後に電気自動車(BEV)は静かで回生ブレーキによる運転も楽なのでオススメです(ただし充電インフラの問題でスーパーチャージャーのあるTeslaに限る)

We are hiring!

マルチデバイスチームでは、OSを問わずモバイルアプリ開発が好きなエンジニアを絶賛募集しています。
フロントエンドだけではなくバックエンドやインフラ(特にAWS)エンジニアも絶賛募集中です。
興味がありましたらぜひご応募ください!

jobs.m3.com