SpresenseとNeural Network Consoleのハンズオンに参加して気づいたこと。
この記事について
この記事では以下のハンズオンに参加して、SonyのNeural Network ConsoleとSpresenseを使ってみた感想を記載している。Neural Network Consoleを使ってSpresenseで動かすCNNを組む際に気をつける点について記載してみた。
ハンズオンでは以下の資料に沿って進めた。Neural Network Console、およびSpresenseの基本的な使用法についてはひとまず使えるようになる。
- Neural Compute Consoleハンズオン
- Spresense ハンズオン
当日貸し出しされた機材はSpresenseにTFT液晶とカメラがついていた。ALGYANさんのイベントはこういった機材を使いやすい形で用意してくれる。気になっていた機材の検証がショートカットができて嬉しい。感謝!
当日ハンズオンの成果について
当日のハンズオンではclassification-hand-signと言う学習済みのサンプルモデル利用した。Neural Compute Consoleからダウンロードし、Spresens上で動作させると言う内容だ。手順通りに進めると、初見でも準備を含めて1時間程度で完了できる。モデル自体はよくある2層のCNNと2層の全結合層で構成されている。28x28 pixelの画像を学習データとして利用する。 Spresenseで動作させるとカメラで撮影された画像がTFT液晶に表示される。さらに、認識したハンドサインに対応したアイコンが、画面の左上に表示される。
動いた。思ったより機敏に反応してくれてオモシロイ。色々できそう!#ALGYAN pic.twitter.com/HrDWpJLGHj
— masato_ka (@masato_ka) June 15, 2019
フレームレートは計測していないが、少しもっさりといった感じだった。機敏に反応してるとは言い難いが、これなら何かに使えそうと言う速度感だった。 グーチョキパーの判定は精度が少し厳しめだった。自分が試した時はチョキがパーとして判定されていた。学習データが単純な白地にグーチョキパーが写っている画像しかなく、もっと汎化できるようなデータを使うと改善さるかもしれない。
Neural Network ConsoleでSpresense向けモデルを作る
用意されたモデルを使うだけではハンズオン時間を持て余してしまった。そこでハンズオン前半で用意した自作のモデルをSpresenseへ入れ動かしてみることにした。学習データはMNISTのデータから4と9のみを抽出し、2クラス分類を行なっている。 モデルの入力と出力に変更はないので、Spresenseのコードは変更せずにモデルだけ差し替えを行なった。しかし、こちらのモデルを動かすことができなかった。
Spresenseで動かすにはモデルのサイズが重要
チュータの方に質問してみたところ、モデルのサイズが大きく、メモリに乗り切らなかったのではないかとのこと。モデル自体はSDカードに保存し、実行時にプログラムメモリ上にロードする。プログラム上はモデルロードに成功しているが、実際にはメモリ上に乗り切れていない可能性があると言う。この部分、検証をしっかりしてないが、モデルサイズが大きいと言うのは本当らしい。 モデルのメモリサイズはパラメータの数に比例する。独自のモデルもhand-signのモデルと同様、4層のCNNのモデルだった。しかし、畳み込み層のフィルタ数や、全結合層のニューロンの数に違いがある。hand-signのモデルはこの部分を調整し、ネットワーク全体のパラメータ数を調整していた。
モデルサイズを小さくするには
Neural Network Consoleでは作成したネットワーク全体のパラメータを画面右下Staticsに表示されるCostParameterで確認できる。また、CostParameterをクリックすると、ネットワークの各層の横にそれぞれの層ごとのCostParameterが表示される。CostParameterが小さくなるようにボトルネックとなる層のパラメータの調整とその結果を確認しながらインタラクティブに操作できる。この点はFWを使って実装するよりも優れているかもしれない。
おそらく、このパラメータの数はDNNの表現力に直結するため、ときたい問題とその目標精度の設定も重要だろう。
感想
Neural Network ConsoleとSpresenseの組み合わは組み込みAIを少ないコストで実現できると感じた。もちろん、Spresense向けにネットワーク構成を工夫する必要がある。しかし、Neural Network Consoleが試行錯誤しやすい仕組みを提供している。組み込みAIを動かすためのプラットフォームは多く提供しているが、敷居が低いと言う点で、Neural Network CosnoleとSpresenseの組み合わせはベストな組み合わせだろう。 今回のつまづきポイントだった、モデルのサイズについては、明らかにモデルサイズが大きい場合はどこかのタイミングで警告が出るようにできるとわかりやすいかもしれない。
Javaライブラリ、KuromojiとKumoで日本語 Word cloudを作成する。
この記事について
この記事ではJavaでWordCloudを作るためのライブラリKumoの使い方を紹介しています。Word cloudは文章中の単語を並べ、各単語の出現頻度にしたがって文字の大きさを変化させる画像です。これにより、直感的に文章の内容や特徴を捉えることができます。
Kumoの概要と日本語形態素解析の検討
JavaのWord cloudライブラリを探したところKumoというライブラリを発見しました。このライブラリはJavaのみで完結しています。
また、ラテン系文字だけでなく、中国語の形態素解析もできるようです。しかし、日本語については形態素解析器が含まれていません。そこで、日本語解析はJavaの形態素解析器としてKuromojiを利用します。
使い方
それでは早速使い方を見ていきましょう。
Javaプロジェクトの依存関係へ追加
前述の通り、日本語の形態素解析にはKuromojiを追加します。まずはMavenまたはGradleの依存関係へKumoとKuromojiを追加しましょう。Kumoはkumo-coreを依存関係に設定すると形態素解析部分を除いたWord cloud作成ライブラリのみをインストールすることができます。Kuromojiについて今回はipadic版を利用します。たの辞書を使う場合もこの後の利用方法に変更はありません。
<dependency> <groupId>com.kennycason</groupId> <artifactId>kumo-core</artifactId> <version>1.17</version> </dependency> <dependency> <groupId>com.atilika.kuromoji</groupId> <artifactId>kuromoji-ipadic</artifactId> <version>0.9.0</version> </dependency>
Kuromojiの形態素解析の実行
Kuromojiの形態素解析後Map<String,Long>という型でデータをまとめます。Keyは抽出した単語、Valueは文章中での出現回数です。 inputTextは文章などが入っている想定です。また、以下の例では固有名詞のみを抜き出しています。
public Map<String,Long> tokenize(String inputText){ List<Token> tokens = tokenizer.tokenize(inputText); Map<String,Long> dataSet = tokens.stream() .filter(t -> t.getPartOfSpeechLevel2().equals("固有名詞")) .map(t -> t.getSurface()) .collect(Collectors.groupingBy(e->e,Collectors.counting())); }
実際にWord cloudを作成するためにはkumo-coreライブラリで提供されているWordFrequencyオブジェクトのListを後述するWordCloudオブジェクトへ渡す必要があります。そのために以下のように変換を行います。
List<WordFrequency> wordFrequencies = dataSet.entrySet() .stream() .map(data -> new WordFrequency(data.getKey(), data.getValue().intValue())) .collect(Collectors.toList());
KumoでWord cloudの作成
実際にWord cloud を作成するにはkumo-coreで提供されるWordCloudクラスを使います。
final Dimension dimension = new Dimension(300,300);// (1) final WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT);// (2) wordCloud.setPadding(2); wordCloud.setBackground(new CircleBackground(200)); // (3) wordCloud.setBackgroundColor(Color.white); // (4) wordCloud.setColorPalette(new LinearGradientColorPalette(Color.RED, Color.BLUE, Color.GREEN, 30, 30)); // (5) wordCloud.setFontScalar(new LinearFontScalar(10, 40)); // (6) wordCloud.build(this.wordFrequencies); // (7) BufferedImage resultImage = wordCloud.getBufferedImage(); // (8)
- (1) Dimensionオブジェクトで作成する画像のサイズを決めるここでは300 X 300
- (2) コンストラクタへ(1)のDimensionオブジェクトを渡してコンストラクタを作成する。
- (3) 半径200の円状にWord cloudを作成する。四角や指定したテンプレート画像に沿った形状にすることもできる。
- (4) 作成画像の背景を白に変更
- (5) 文字のグラデーションを設定
- (6) フォントサイズの設定
- (7) 作成元のデータが入っているList
オブジェクトを渡しビルドする。 - (8) 作成された画像をBufferedImageとして 取得する。
最終的に出力されたBufferedImageオブジェクトをファイルに保存します。画像の拡張子はデフォルトでpngとなっていますが、設定で変更できるようです。
作成してみたWord cloudの画像
試しに、このブログに対して処理をかけてみたのが以下の結果です。見事に横文字単語だけで構成されています。あんまり日本語の形態素解析をしたありがたみがないです。
ニュース記事なんかで試してみるといいかもしれませんね。
まとめ
自分のブログにWord Cloudを実行すると今までにどんなブログを書いていたのかわかりやすくなります。今後のブログ内容や自分の興味関心などをアバウトに把握できていい感じです。
if-up 2019に参加した話。
この記事について
この記事ではソラコムさん主催のif-up 2019へ参加した感想について記載しています。if-upは2017年に開催されたソラコムさん主催のイベントです。その後同名のイベントはなかったのですが、今回パワーアップした形で帰ってきました。
if-up 2019の概要について
前述の通り、if-upは2017年に同名イベントが開催されましたが、今回は少し毛色が違ったイベントになったと感じました。詳細は以下のイベントページにを確認いただければと思います。
毛色が違った大きな点としてはこれまでのイベントではIoTにおける課題解決をソラコムサービスでどうやって解決するかという内容が主体となっていたのですが、今回のイベントではその部分は少しトーンダウンしています。日本のものづくり、サービス開発は今どうなっているのか、みんな何を課題に取り組んでいるのか?そんなトーンのイベントとなっていました。 イベント冒頭のキーノートセッションでは「プロダクトの裏にはパッションをもった人とチームがいる!」、「プロダクトづくりの前提が変わった」、「日本からもっと良いプロダクトが出てもいいはず」という問いかけから始まり、大変興味深い内容のイベントとなりました。イベント全体を通して特に印象に残ったポイントについて紹介していきます。
if-upで印象に残ったポイント
世の中にないものを生み出すということ
午前のキーノートでの主題的なテーマだと感じたことです。新しいプロダクトを作る際に、そのコンセプトが果たして正しいのか、それは便利なのかは誰にも分かり得ないことです。良いプロダクトを作るためにまた、作る側のパッションを保つためにもこういった不安を払拭していく必要があると思います。 そんな中でGroovXさんとソラコムさんのプロダクト開発で共通しているなと思ったことが、MVPを作り、ユーザへの提示を素早く行っていくことが一つの会になるのだなと思いました。Agile的な取り組みでは当たり前の解決策ではなるのですが、論より証拠というのはパワポ100ページよりも説得力がある非常にためになるお話でした。 GroovXさんのLOVOTの開発に関するお話の中でLOVOTはロボットではあるけども「便利ではなく心のケアを中心にプロダクトを作った」けれどもまだ形も無いもので投資家の理解も得られなければ、身内からも不安になる。そこで、MVPを作って仮説検証を繰り返し自分たちの目指す方向を正しく見定めたとのことでした。またソラコムさんのお話でもBeamからFunnelそしてHarvestとプロダクトが進化した経緯をベースに同様のことをおっしゃられていたと思います。
日本のプロダクトが売れないのはなぜか?
日本のプロダクトが売れないのは良いプロダクトが作れないのではなく、良いプロダクトの定義が変わったという話が興味深かったです。つまり日本のプロダクトは昔から同じもので過去の基準からすればいいもののはずだけど、そもそも世の中が考える良いプロダクトの基準が変わったため売れなくなってしまったという話です。じゃあ、そもそも「新しい良いプロダクトとはなんなのか?」について明確な定義は出ていなかったと思いますが、パネラーの方達から語られたのは
- 良いプロダクトの定義が変わったよりはトレンドに振り回されず芯を通したプロダクト開発が必要である。
- 自分たちが何をやっているのかしっかりをパッションを持つ。
- 自分たちが何者なのかをはっきりさせる。
ということでした。プロダクトの機能を提供するのではなく、その機能が与える価値をはっきりとさせる、自分たちがユーザへ与える価値か解決する課題をしっかりと定義すること。これが良いプロダクトを作る秘訣なのかなと思ったり。少し前に流行ったコトづくりと似通ったところはありますが、プロダクトの価値としては本質的なんだろうなと思いました。
まとめ
良いプロダクトをいかに作り出していくのかというのは非常に難しいテーマだと常日頃思います。今日のif-up2019参加してまだまだ振り返りきれていないところもあるのですが、やはり自分たちがテクノロジーを使い、いったい何に取り組むのかを明確化し定義する、それを素早く形にしていき検証を行っていくのが必要なのかなとも思います。それは大変難しいことでもあるのですが。。。
grpc-spring-boot-starterでSpringBootへgRPCを導入する。
# この記事について この記事ではgrpc-spring-boot-starterを使ってSpringBootでgRPCを利用する方法について記載します。主に自分向けの備忘録的記事となります。
プロジェクトの設定
ビルドツールはMavenを利用します。SpringBootのライブラリ作成後、pomのdependenciesに以下を追加して依存関係にgrpc-spring-boot-starterを追加します。 grpc-spring-boot-starterはgRPCをSpringBootで利用できるようにするAutoConfigurationを実行します。
<dependencies> <dependency> <groupId>io.github.lognet</groupId> <artifactId>grpc-spring-boot-starter</artifactId> <version>3.1.0</version> </dependency> </dependencies>
ビルドを実行するプラットフォームを特定するためにプラグイン拡張を追加します。プロトコルバッファをビルドするためのprotocコマンドダウンロードに利用します。
<build> ... <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.5.0.Final</version> </extension> </extensions> ... </build>
さらにpurotobuf-maven-pluginを追加することで、Mavenのビルドプロセスの中でプロトコルバッファをコンパイルできるようにします。
<build> ... <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.6.0:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.18.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> ... </plugins> </build>
上記でgRPC導入の設定は完了です。
gRPCのインタフェース定義
gRPCではprotoファイルと呼ばれるファイルでRPCの定義を記述します。記述されたprotoファイルからprotobuf-manve-plugin(実際にはprotocコマンド)がgRPCのサーバ側の抽象クラスとクライアントコードを自動生成します。
protoファイルの作成
以下のようなprotoファイルで定義します。 先頭の「option java_package」で生成後のコードのパッケージを定義します。プロジェクトのパッケージに合わせて適宜変更します。
syntax = "proto3"; option java_multiple_files = true; option java_package = "ka.masato.grpc.demo.grpcmavendemo"; option java_outer_classname = "GreetClass"; package greet; service Greet{ rpc greeting (GreetRequest) returns (GreetResponse); } message GreetRequest{ string value = 1; } message GreetResponse{ string value = 1; }
protoファイルの文法については以下を参照ください。
protoファイルのビルド
protoファイルのビルドは前述のようにMavenのビルドプロセスの中で実行れます。以下のようにビルドを実行します。
$ mvnw clean package install
実行後、target/generated-souces/protobuf
配下に生成されたコードが格納されています。IntelliJ IDEAで実行した際にはclassパスにも追加されているはずのなので、そのまま、srcフォルダ配下のパッケージから参照することができます。
gRPCの実装
生成されたコードをベースにサーバとクライアントを実装します。
サーバ側の実装
生成されたコードに含まれるGreetGrpc.GreetImplBaseを継承したクラスを作成します。この抽象クラスにはprotoファイルで定義したサービスがメソッドとして定義されており、これをオーバライドすることでAPIを実装します。また、継承クラスにはgrpc-spring-boot-starterで定義されている@GRpcServiceアノテーションをつけることで、gRPCのサーバとして登録されます。
@GRpcService public class endpoint extends GreetGrpc.GreetImplBase{ @Override public void greeting(GreetRequest request, StreamObserver<GreetResponse> responseObserver) { String value = request.getValue(); GreetResponse greetResponse = GreetResponse.newBuilder().setValue("Greeting!"+ value).build(); responseObserver.onNext(greetResponse); responseObserver.onCompleted(); } }
クライアントの実装
クライアント側ではスタブを作成し、スタブ経由でサービス側のメソッドを呼び出します。正確かはわかりませんがManagedChannelはgrpc-spring-boot-starterでbean定義されていると思います。
public class GreetClient { private final GreetGrpc.GreetBlockingStub stub; public GreetClient(ManagedChannel managedChannel) { this.stub = GreetGrpc.newBlockingStub(managedChannel); } public String getHello(){ GreetRequest greetRequest = GreetRequest.newBuilder().setValue("Hello").build(); GreetResponse greetResponse = this.stub.greeting(greetRequest); return greetResponse.getValue(); } }
まとめ
grpc-spring-boot-starterを使うとSpringBootで簡単にgRPCを実装することができました。また、proto-buf-mavenプラグインを利用することで、Mavenのビルドプロセスの中でプロトコルバッファのファイルからgRPCのコードを自動生成することができました。gRPCはprotoファイルで定義した内容からサービスの実装インタフェースと対応するクライアントコードを自動生成でき、サービス間通信のインターフェースを実装と定義を紐付ける良い方法だと思います。実際の開発にはprotoファイルの管理やなど実装以外に工夫が必要そうです。
SORACOM Lagoonと AndroidThingsでIoT X AIをやってみた。
この記事について
この記事はSORACOM Adventcalendar 2018 18日目の記事です。SORACOM Adventcalendar 2018もいよいよ終盤に差し掛かってきました。今回は2018 年11月24日に開催されたIoTつくるよで展示した SORACOM LagoonとAndroidThingsを使った物体温度計測システムについて紹介します。当日のLTの資料は以下の通りです。
物体温度計測とは?
温度センサなどで部屋の温度や外気温を計測し可視化・モニタリングすることはIoTのユースケースとして一般的に紹介される例です。こう言った場合、部屋の住環境のモニタリングや商品が保管してある倉庫などの環境モニタリングとして実施されることが大半でしょう。 しかし、温度計測が必要であるが、前述の例のような部屋や空間といった面としてのセンシングではなく、ピンポイントで温度を計測したい場合が出てきます。例えば機械設備の保守では設備のある特定の部分の温度上昇を検知したい場合です。また、ショウケースに入った食品などの品質監視を行う場合、ショウケース内の温度を1箇所測っただけでは実際の食品の温度を知ることはできません。 こういった場合、測りたい物に直接センサを貼り付けて温度を監視したくなりますが、以下の理由から難しいと考えます。
- 計測対象にセンサの設置が困難
- 計測する個数があらかじめ特定できない
- 計測箇所があらかじめ特定できない。
この課題を非接触温度センサとDeep Learningによる物体検知を行うことで解決します。また取得したデータをSORACOM Lagoonでダッシュボードとして提供します。
作成したシステムの仕組みについて
全体概要
全体構成は以下のようになっています。
詳細については以下で順に説明します。
Android ThingsとSORACOMの接続について
今回デバイス構築に利用したのはGoogleが提供しているIoTデバイス向けのOSであるAndroidThingsを利用します。Android Thingsについての紹介記事は以下の過去記事を参照ください。
Android ThingsはSIMを利用する環境が整っていないため、SORACOMに接続する際はSORACOM Inventoryからデバイス登録を行い、デバイスのシークレットを取得します。取得したシークレットを元にSORACOM HarvestのAPIへインターネット経由でデータを送信します。具体的な手順は以下ソラコムさんのサイトを参照してください。
AndroidThingsからAPIを叩く際はokhttpを使い。以下のコードスニペットを使い、データの送信を行なっています。実験用のため、デバイスIDやシークレットをハードコートしていますが、実際にはAndroidのKey storeなどに保存しておくと良いと思います。
private static final String HARVEST_ENDPOINT = "https://api.soracom.io/v1/devices/"; private static final String DEVICE_ID = "<デバイスID>"; private static final String DEVICE_SECRET_KEY = "<デバイスシークレット>"; private OkHttpClient mOkHttpClient; private ObjectMapper mObjectMapper; String payload = mObjectMapper.writeValueAsString(harvestSummaryPayload); MediaType MINE_TYPE = MediaType.parse("application/json; charset=utf-8"); //"x-device-secret: <シークレットキー>" Request request = new Request.Builder() .url(HARVEST_ENDPOINT+DEVICE_ID+"/publish") .addHeader("x-device-secret", DEVICE_SECRET_KEY) .addHeader("Content-Type", "application/json") .post(RequestBody.create(MediaType.parse("application/json;charset=utf-8"), payload)) .build(); Response response = mOkHttpClient.newCall(request).execute(); response.body().string();
物体検出について
今回の物体検出は学習済みのTensorflowモデルをTensorflow liteモデルへ変換し、AndroidThings場で動作させました。動作させたモデルはSSD Mobilenet v1 cocoと呼ばれるモデルです。AndroidThingsでの動作については以下の過去記事を参照ください。
非接触温度センサについて
非接触温度センサはPanasonic社のAMG8833赤外線アレイセンサを利用します。このセンサは8X8の格子状に非接触で温度データを取得することができます。データの取得インタフェースはI2C です。エアコンに内蔵され、人発見などの利用されるセンサーです。
実行結果
デバイス側でおの物体検知と温度計測について
AndroidThings側での実行結果は以下の動画のようになっています。物体検出でマグカップを認識しています。その後、マグカップにお湯を注ぐことで発生する温度上昇をセンサーで捉えています。このようにAIだけ、センサーだけではできない事象を多次元的に捉えることがAI X IoTの醍醐味でしょう。
SORACOM Lagoonでの可視化について
SORACOm Lagoonでの可視化は以下のようになっています。このダッシュボードでは缶コーヒーの温度と個数を計測しています。これらを1つのデバイスで実現出来つところがみそです。
まとめ
今回はIoT X AIということでAndroidThingsで取得したセンサ情報と画像認識の結果をSORACOM Lagoonで可視化させてみました。ソラコムのサービス自体は昨年まではセルラー前提といった印象が強かったですが今年のDiscoveryイベントを境にセルラーだけでなくより幅の広いIoT プラットフォームとしての進化を遂げています。そんなソラコムサービスだからこそ、IoT X AIなサービスでも活躍できるのではないのでしょうか。来年もソラコムさんからますます目が離せません!
SORACOM LTE-M Buttonで家庭内PoCをやってみた話
1. この記事について
この記事はSORACOM LTE-M Button powerd by AWS Advent Calendar 2018 8日目の記事になる。前回このブログではSORACOM LTE-M ButtonがIoTデバイスとしてとて素晴らしいお手本となっていることを紹介した。
この意見は今も1mmとして変わってない。その上で、どんな素晴らしいデバイスを使ったとしてもアプリケーションとユーザとの関係を考えユースケースを実装することが価値になるということをお伝えしたい。そうでなければせっかくの素晴らしいデバイスを台無しにしてしまう。今回はおうちハック的にSORACOM LTE-M Buttonを使ってみたお話となる。
2. 検討したユースケース
今回SORACOM LTE-M Buttonを利用して実装したアプリケーションのユースケースは日用品の在庫管理ユースケースである。
これはSORACOM LTE-M Buttonをクリックするたびに日用品の在庫の数をカウントする機能を持っている。あらかじめ備蓄品の数を設定しておき、備蓄品を利用したらボタンをワンクリックする。そうすると、在庫数を減算していく仕組みである。管理している在庫数を可視化させることでリアルタイムに備蓄品の数を確認することができる。家庭内でよく使う備蓄品としてトイレットペーパやティッシュといった日用品から卵などの食品まで色々なものを割り当てることができる。今回は冷蔵庫の卵の数をカウントするEgg Counterを実装した。
2.1 ユースケースにおける課題感
ユースケースに対する課題として考えたことは、「帰宅途中に買い物をする際に冷蔵庫の中身を覚えておらず買い物に苦慮する場面」であった。 例えば夕飯の支度に卵を使いたいが、卵の残数やその賞味期限などを出先で確認することが難しい。我が家は共働きの2人暮らしである。そののため、特にこういった食品の残数について、「お互いがいつ使ったかわからない」ことから残数の把握は困難になる。
2.2 在庫の減り具合を見ることの意義
在庫状況を可視化することで上記の課題に対して、出先にて最新の在庫状況を確認することが可能となる。そのため、無駄な買い物を抑止することができる。また、可視化状況を共有することでコミュニケーションにより多重購入という悲劇を未然に防ぐ手立てともなる。
2.3 本家ダッシュボタンとの違い
本家ダッシュボタンでは似たような課題に対して、無くなる、無くなりそうなタイミングですぐに注文できるという価値を提供している。一方で現在の家の中の在庫数については管理することができない。この場合、上記に挙げた課題感に対しては対応することができない。また時系列で在庫の消費量を記録することで将来の消費予測やカイゼン活動につなげることができる。
3. Egg Counterのアーキテクチャ
ここで実際に作成したSORACOM IoT Buttonを利用した在庫管理アプリケーション、Egg Counterについて紹介する。
3.1 アーキテクチャ方針
Egg Counterのアーキテクチャを決定する上で以下の二点をポイントとしてて検討を行った。
- 簡便に在庫の管理を実現する機能
- 簡易PoCに的を絞り簡易なつくりとすること。
1についてはセンサーなどは使わずにSORACOM Buttonを、使うことで簡単に在庫の記録を行えるようにした。 2.については既存サービスを活用することで構築の手間を省いた。また利用するサービス数を絞れるように各サービスの使い方を工夫した。
3.2 構成
上記アーキテクチャ方針にしたがって以下のような構成とした。
以下のように冷蔵庫から卵を取り出すごとにSORACOM LTE-M Buttonを押すことで在庫数をカウントしていく。カウントされた在庫数は Lagoon上で可視化されるようにした。データの永続化自身はSORACOM Harvestに任せ、AWS Lambdaからアクセスするようにしている。
- ボタンに割り当てられたイベントは以下のようになっている。
ボタンイベント | 動作 | 意味 |
---|---|---|
シングル | 在庫減算 | 卵を使った時に卵の在庫を減らす。 |
ダブル | 在庫加算 | 卵の補充や誤押の際の在庫修正に利用する。 |
ロング | 在庫のリセット | 卵を新規に補充した際に設定された値に在庫を更新する。 |
3.3 AWS Lambda のコード
Lambdaのコードは以下のリポジトリに掲載している。
CloudFormationを使いデプロイすることができる。今回は先日のAWS reInventで公開されたIntteliJ IDE の AWS Toolkits pluginを使って開発を進めた。
Lamda ファンクション本体は以下のようにクリックに応じて各イベント処理にディスパッチするコードのみになっている。
def lambda_handler(event, context): click_type = event['deviceEvent']['buttonClicked']['clickType'] if click_type == "SINGLE": do_single_click_event() logger.info("Called single click event.") if click_type == "DOUBLE": do_double_click_event() logger.info("Called double click event.") if click_type == "LONG": do_long_click_event() logger.info("Called Long press event.") return {"result":"success"}
SINGLEクリックイベントのメソッドではSORACOM APIから現在の在庫数を取得するget_latest_remaining
メソッドを実行し、在庫の減算を行なっている。減算した結果をpersistent_remaining
HarvestのAPIで送っているようにしている。
def do_single_click_event(): latest_remaining = get_latest_remaining() remaining = latest_remaining - 1 if latest_remaining > 0 else 0 persistent_remaining(remaining)
ダブルクリックやロングについても加算、リセットのみが違うだけで動きは同じである。ソラコムのAPIについてもオーソドックスにアクセスすれば問題ない。この部分は今年ソラコム側でセルラー回線以外へサービスの対応を進めているため、実現できるようになった。
参考2では記載されていないが、参考1で入れたデータを取得するためのエンドポイントはhttps://api.soracom.io/v1/data/Device/{DEVICE ID}?sort=desc&limit=1
となる。詳細は上述のGitHubのコードをご覧いただきたい。
4. 改善ポイント
4.1 AWS Lambdaに渡すキーの多さ
SORACOMHarvestの WEB APIとSORACOM APIのDATA APIを使うことで、AWS Lambdaは以下の4つの情報を持つことになる。 これらはAWS Lambdaに環境変数として設定している。SORACOM Harvestへデータを送信するためにはAWS Lambdaをデバイスと登録してキーを払い出す必要がある。SORACOM Buttonが出てきたタイミングでボタンの情報をHarvestに連携するために従来のSORACOM APIとHarvestのAPIを一緒にしてもいいと思う。AWS側にDB持たせればいいというのはごもっとも。
キー名 | 説明 | 用途 |
---|---|---|
デバイスID | SORACOM Inventoryから払い出されたデバイスID | SORACOM Harvestへデータを送る際に利用 |
デバイスシークレット | SORACOM Inventoryから払い出されたデバイスのシークレットキー | SORACOM Harvestへデータを送る際に利用 |
Authキー | SAMユーザのAuthキー | SORACOM Harvestからデータを取得する際に利用 |
AuthキーID | SAMユーザのAuthキーID | SORACOM Harvestからデータを取得する際に利用 |
4.2 AWS Lambdaの環境変数
環境変数の値として記号を含む文字列を設定するとエスケープされてしまう。また、環境変数から文字列として取り出した場合、エスケープされた文字列が取り出されるため、エスケープを除去する必要がある。今回の場合、SORACOM Inventoryで払い出したデバイスシークレットキーに「=」が含まれており、これが「\」でエスケープされていた。そのため、以下のようなコードでエスケープ文字を除去した。
KEY_NAME = os.environ['key name'].replace('/','')
5. ユーザレビュー
仕組み自体の構築は1〜2時間で完了し、いざ家庭内 PoCとして投入してみた。
5.1 ユーザの感想
意気揚々と仕組みの説明と使い方、意義を説明した結果ユーザから「めんどくせぇ」という感想をいただいた。UXへの敗北である。「ボタンを押す煩わしさ>卵の個数がわかるメリット」の図式が出来上がったために発生した問題だ。前述したように、仕組みやデバイスが良くてもそれを活用するアプリケーションの価値に問題があった。
6. まとめ
SORACOM LTE-M Buttonは非常に優れたデバイスである。しかし、それを活かすユースケースをしっかりと作り込むべきだろう。今回は卵を取り出すという行為に無理やりボタンを押すという行為を繋げてしまい、ユーザへの手間を増やす結果となった。SORACOM LTE-M Buttonを活かすためには。ボタンを押すという行為がユースケースで無理なく出てくることが重要じゃないかと思う。良いデバイスなだけに見落としやすい。
SORACOM LTE-M Button powerd by AWSがIoTアーキテクチャの優れたリファレンスモデルな件
この記事について
この記事ではSORACOM LTE-M Button powerd by AWSについてのファーストインプレッションを紹介する。7月の発表から発売まで首を長くして待ち、ようやく手元に届いたこの製品。IoTを実現するシステム、デバイスのお手本と言ってもいいくらい綺麗な作りになっていた。この記事ではSORACOM LTE-M Button powerd by AWSがなぜIoTのお手本と言えるのか考察していく。 以下のツイートをしっかりと文章にした内容だ。
開封後あっさりメール送れてすげーってなってる。使ってみてアプリケーション層はAWS、デバイス管理はSORACOMサービスが前段でやってる。お手本みたいな綺麗な作り。SORACOMの正しい使い方をユーザに刷り込む良いサービス。 pic.twitter.com/qaWXsuuqHQ
— masato_ka (@masato_ka) 2018年11月3日
SORACOM LTE-M Buttonについて
SORACOM LTE-M Buttonは7月に行われたSORACOM Discoveryイベントで発表されたソラコム初の自社デバイスだ。中身はAWS IoT ボタン(Amazon dashボタンのベース)で、AWS IoT 1Clickサービスを使って利用することができる。 このデバイスができることはAmazon dashボタンのように、ボタンをクリックすること。ボタンのクリックは3パターンあり、それぞれシングルクリック、ダブルクリック、長押しである。ボタンをクリックするとAWS IoT 1Clickへイベント情報を送信する。ユーザはAWS IoT 1Clickに送られたイベントを処理することで任意のアプリケーションを実装することができる。処理はAWS Lambdaで記述する。 このようにデバイス自体の機能は本家AWS IoTボタンと一緒である。しかし、SORACOM LTE-M Button powerd by AWSはKDDI社の LTE-Mと呼ばれる、LTEの通信網を利用したLPWA規格を採用している。この回線を利用することでWiFiを必要とせず、デバイス単体でAWSへのコネクティビティを確保している。
何がIoTアーキテクチャのリファレンスとして優れているのか?
ここからはSORACOM LTE-M Button powerd by AWSがIoTのお手本たる理由について語っていきたい。
1. シームレスなデバイスアクティベート
SORACOM LTE-M Button powerd by AWSはパッケージ開封後、すぐにAWSに接続することができる。すぐという言葉は曖昧だがおそらく最短30秒もあれば十分な時間だろう。本体の裏にあるデバイスコードをAWS IoT 1Clickのデバイス登録画面に入力し、画面の案内に従い、デバイスのボタンを一回クリックすれば完了する。 もちろんAWS IoT 1Clickの仕組みがシンプルという見方もできる。しかし、最も大きい理由はLTE-Mを使うことで、WiFi接続をすっ飛ばすことができるという点だ。 従来この手のデバイスはWiFiを利用していた。そのためにデバイスを一度設定モードで起動(WiFiアクセスポイントになったりする)しスマートフォンから専用アプリかWebブラウザで接続し、WiFiのパスワードや酷い場合は専用クラウドサービスのパスワード入力を必要というお世辞にもスマートとは言えない解決方法を提供してくれていた。またWiFi接続を利用することで実質的に屋内での利用に限定されていた。この問題をLTE-Mとソラコムの基盤でものの見事に解決してくれたのだ。 当然利用するユーザにとって接続の利便性を提供するだけでなく、利用するシーンを限定しないという利点がある。ユーザがデバイスを利用するために何を提供すれば良いのか、非常に参考になる。
- 実際の設定方法がみたい方は以下公式ドキュメント参考のこと。
2. 標準で提供されるデバイス管理機能
SORACOM LTE-M Button powerd by AWSはAWSへの登録以外にソラコムの対応サービスへ登録を行う必要がある。登録しなくても利用はできるのだが、通信料の更新などができない。欲を言えばこの部分はAWS登録と連動してほしかった。が、この一点に目を瞑れば、この登録もユーザにはメリットがある。なぜならば登録することでデバイスの管理がソラコムのユーザコンソール画面から行えるからだ。実際の管理画面は以下のように見える。
残りのクリック回数や残電池量を見ることができる。また、最後に接続した時間やその際のイベントのペイロードとしてJSONデータを確認することができる。デバイスや障害調査だけでなく、ユーザの利用状況調査などIoTサービスの本質的な情報の収集という点で非常にありがたい情報だ。デバイス管理を行う上で何の情報に気をつけて取得すれば良いのか参考になる。
3. 責務の境界とセキュリティ
最後にユーザの 目に触れないが、無意識のうちに重要な部分だ。実は前項で紹介したシームレスなデバイスアクティベートも標準で提供されるデバイス管理機能も、ソラコムサービスとAWSの役割がしっかりしているため、結果として実現されいる機能だと考えている。 現状知りうる範囲から推測できるSORACOM LTE-M Button powerd by AWSのアーキテクチャを起こしてみた。
SORACOM LTE-M Button powerd by AWSはKDDI社のLTE-M網を経由してソラコムの基盤につながる。ここは他のソラコムサービスと同じだと考えられる。そこからSORACOM Beamを使ってAWS IoT 1clickへ接続されているようだ。そのため、公衆インターネット回線へ出ることなくデータをセキュアにAWSへ転送できる。 また、デバイス管理機能はソラコムのサービス内で完結している。もちろんAWS側で同等の機能を組むこともできるだろうが、基本的にはAWSはアプリケーションの実現に集中することができる。 つまり、アプリケーションを実現するAWSサービスとデバイスの安全なコネクティビティと管理を実現するソラコムサービスというサービス間の責務の分解が施されている。IoTサービスで様々なサービスが似たような機能を重複して提供している。その中でソラコムのサービスの位置付けとしてIoTアーキテクチャの下回りをしっかりと提供し、他者クラウドサービスはアプリケーション実現のみに利用できるという一種のレイヤー構造を提示しているのではないだろうか。今回のSORACOM LTE-M Button powerd by AWSでは難しいかもしれないが、こういったレイヤー構造を組んでおけば、アプリケーション層をオンプレミスな環境として組むことや、費用やサービスのスケールに伴い、利用するクラウドを変えいてくことをユーザやデバイスへの負担なく実現できることだろう。IoTの全体アーキテクチャを考える際に非常に参考にしたい点だ。
まとめ
このようにソラコムの基盤とAWSのサービスをうまく繋ぎこみ、デバイスの提供と運用を実現している。ソラコム自社で提供する基盤だけあってソラコムのポテンシャルが十分に発揮できていると思った。もちろんエンドユーザ向けサービスとしてのユースケースやビジネスモデルは存在しない。これはこのデバイスを使うユーザが作り上げる必要がある。しかし、どうやってデバイスをユーザに届けるか、どうやって自分たちのビジネスモデルを実現するアプリケーションを作るか、どうやってサービスを運用していくか、こういったIoTサービスを実現する上考えなければならない問題についてその解の示唆を与えてくれている。SORACOM LTE-M Button powerd by AWSはまさしくIoTアーキテクチャの優れたリファレンスモデルとなっている。きっと僕たちがいつまでも実現しないからソラコムが自分たちで作ってしまったのだ!
ちなみに現在(2018年11月4日)キャンペーン価格中で3980円で購入することができる。キャンペーンの終了時期は未定だが、この機会にぜひこのデバイスを体験していただきたい。Amazon dashボタンをハックして喜んだり、温度センサの値をWEBブラウザでグラフにしてIoTとか言って喜んでいる場合ではない。