データのシリアル化と逆シリアル化の例
このトピックでは、Alexa Gadgets Toolkitインターフェースのディレクティブとイベントをシリアル化(エンコード)および逆シリアル化(デコード)するサンプルコードについて詳しく説明します。ここではC言語の実装を取り上げていますが、PythonやJavaなどのほかの言語にも、この概念を応用できます。
- ステップ1: リソースの取得
- ステップ2: ユーティリティファイルのコピー
- ステップ3: .protoファイルのコンパイル
- ステップ4: サンプルのコンパイル
- ステップ5: サンプルの実行
- (オプション)ステップ6: 静的に割り当てられたデータサイズの変更
ステップ1: リソースの取得
最初の手順は、以下のリソースを取得することです。
- nanopb .protoコンパイラをダウンロードする – C言語でプロトコルバッファーを使用するには、nanopbの使用をお勧めします。nanopbは、ANSI C準拠で実装された小規模コードのプロトコルバッファーです。特にマイクロコントローラーでの使用に適していますが、あらゆるメモリが制限されたシステムに対応します。nanopbをインストールするには、以下の手順を実行します。
- Nanopb Downloadsでnnanopb 3.xをダウンロードしてください。このサンプルコードはnanopb 4.xでは動作しません。
- nanopbダウンロードのコンテンツを展開します。展開されたnanopbディレクトリには、.protoファイルをコンパイルする実行可能ファイルが含まれます(つまり、*.cファイルおよび*.hファイルを取得します)。また、protobufエンコードされたデータをエンコードおよびデコードする関数とデータ構造を含むヘルパーファイルも含まれます。
- Alexa Gadgetsサンプルコードをダウンロードする – GitHubのAlexa Gadgetsサンプルコードリポジトリを取得します。このリポジトリには、Alexa Gadget .protoファイルとサンプルコードが含まれます。
ステップ2: ユーティリティファイルのコピー
前の手順でダウンロードしたAlexa Gadgetsリポジトリの/examplesディレクトリに、nanopbディレクトリから以下のファイルをコピーします。これらのファイルは、protobufエンコードされたメッセージのエンコードとデコードに必要な手法とデータ構造を定義するユーティリティファイルです。
- pb.h
- pb_common.c
- pb_common.h
- pb_decode.c
- pb_decode.h
- pb_encode.c
- pb_encode.h
ステップ3: .protoファイルのコンパイル
以下のように、Alexa Gadgets .protoファイルを、ガジェットコードから参照できるクラスにコンパイルする必要があります。
- ダウンロードしたAlexa Gadgetsサンプルコードリポジトリの/examplesディレクトリに移動します。
- compile_nanos.sh(MacまたはLinuxの場合)またはcompile_nanos.bat(Windowsの場合)を開き、指定したPROTO_COMPILE_PATHにnanopb .protoコンパイラがあることを確認します。
- /examplesディレクトリから、compile_nanos.sh(MacまたはLinuxの場合)またはcompile_nanos.bat(Windowsの場合)を実行します。この操作で、Alexa Gadgetsサンプルコードリポジトリの.protoファイルがすべてコンパイルされ、生成されたCファイルとヘッダーソースファイルが/examplesディレクトリに入ります。
ステップ4: サンプルのコンパイル
/examplesディレクトリから、以下のコマンドを使用してproto_sample.cをコンパイルします。
gcc -I. -DPB_FIELD_16BIT notificationsSetIndicatorDirectivePayload.pb.c notificationsSetIndicatorDirective.pb.c alexaDiscoveryDiscoverResponseEventPayload.pb.c alexaDiscoveryDiscoverResponseEvent.pb.c alexaDiscoveryDiscoverDirective.pb.c alexaDiscoveryDiscoverDirectivePayload.pb.c alexaGadgetStateListenerStateUpdateDirective.pb.c alexaGadgetStateListenerStateUpdateDirectivePayload.pb.c alexaGadgetSpeechDataSpeechmarksDirective.pb.c alexaGadgetSpeechDataSpeechmarksDirectivePayload.pb.c pb_common.c pb_decode.c pb_encode.c directiveHeader.pb.c eventHeader.pb.c directiveParser.pb.c eventParser.pb.c proto_sample.c -o proto_sample
ステップ5: サンプルの実行
Alexa Gadgetsディレクティブとイベントをバイナリーからエンコードおよびデコードし、結果を印刷する./proto_sampleを実行します。ディレクティブをエンコードし、イベントをデコードする関数は、例を示すためだけに表示しています。現実のアプリケーションでは、ガジェットはディレクティブをデコードし、イベントをエンコードします(その逆ではありません)。
以下の表に、サンプルコードに含まれる関数をまとめます。
関数 | 説明 |
---|---|
decode_directive() |
Alexa Gadgetsディレクティブをすべてデコードします。関数がインターフェースの名前空間とディレクティブ名を認識できない場合、エラーがプリントされます。この関数には自作のディレクティブの解析コードを追加できます。 |
decode_event() |
Alexa Gadgetsイベントをすべてデコードします。関数がインターフェースの名前空間とイベント名を認識できない場合、エラーがプリントされます。この関数には自作のイベントの解析コードを追加できます。 |
encode_set_indicator_directive() |
以下の
|
encode_sample_discover_response_event() |
以下の
|
encode_sample_discover_directive() |
以下の
|
encode_sample_state_update_directive() |
以下の
|
encode_sample_speechmarks_directive() |
以下の
|
main() |
上記の関数を呼び出します。 |
出力
サンプルを実行すると、以下のように出力されます。
(オプション)ステップ6: 静的に割り当てられたデータサイズの変更
Alexa Gadgetsサンプルコードリポジトリには、ペイロードに1つ以上のフィールドを含む各ディレクティブおよびイベントの.protoファイルに対応するオプションファイルがあります。
このオプションファイルは、ペイロードの各フィールドの最大サイズを指定します。これにより、フィールドのメモリを静的に割り当てるよう.protoコンパイラに指示します。たとえば、Discover.Response
イベントのオプションファイルは、以下のようにcapabilities
配列のサイズを定義します。
alexaDiscovery.DiscoverResponseEventPayloadProto.Endpoints.capabilities max_count:32
コンパイラがコードを生成すると、32の機能にメモリを割り当てます。max_count
を変更してコードを再コンパイルすることはできますが、最大値を増やすとデコードが失敗する可能性がありますので、注意してください。
メモリの使用状況を最適化したい場合は、max_count
(またはその代わりに指定されたmax_size
)を減らしてください。これにより、作成する.protoメッセージにコンパイラが静的に割り当てるメモリが減少します。