MbedプログラムをVisual Studioでデバッグする
前回に続き、MbedプログラムをVisual Studioでデバッグしてみました。
元ネタはこちらです。 blogs.msdn.microsoft.com
元ネタにあるとおり、デバッグができるのはPreviewのVisual Studio 2017 15.6です。そのため、前回と違ってVisual Studio 2017 Previewを使いました。Visual Studio 2017 Previewはここからダウンロードできます。
- Windows 10 64bit 1709
- Visual Studio 2017 15.6.0 Preview 3.0
- NUCLEO-F401RE
プログラムの作成
前々回と同じです。
Embedded開発とIoT開発をインストール
Visual Studioに含まれている、Visual C++ tools for CMake and LinuxとEmbedded開発とIoT開発のオプションをインストールしておく必要があります。
Visual Studioを英語表示にしておく
前回にVisual Studioを英語表示にしておかないとBuild/Cleanのコンテキストメニューが表示されなかったので、早めに英語表示にしておきます。ツール -> オプションの国際対応の設定にある言語をEnglishにして、Visual Studioを再起動してください。
Visual Studioで開く
前々回とほぼ同じです。
File -> Open -> Folderでエクスポートしたプログラムを開いてください。そして、Project -> Edit Settings -> CppProperties.jsonを選んで、自動的に作られたCppProperties.jsonを下記に入れ替えて保存してください。
Project -> Edit Settingsが表示されないときは、main.cppをダブルクリックで開くと表示されます。
CppProperties.json
{ "configurations": [ { "inheritEnvironments": [ "gcc-arm" ], "name": "gccarm", "includePath": [ "${env.INCLUDE}" ], "defines": [ ] } ] }
Visual Studio 2017 15.5の場合、"gcc-arm"を"gcc_arm"にしないと正常に動作しませんでした。
Visual Studio 2017 15.6.0 Preview 3.0の場合、ソースの探索にとても時間がかかるようです。CPU負荷が気になる場合はしばらく放置しましょう。
ビルド
前回と同じです。
Makefileを右クリックしてBuildを選ぶとビルドできます。
デプロイ
Nucleo_blink_led.binを右クリックしてConfigure Tasksを選んでcopyコマンドをタスクに割り付ければVisual Studioからデプロイできるようになります。
tasks.vs.json
{ "version": "0.2.1", "tasks": [ { "taskName": "Deploy", "appliesTo": "BUILD/Nucleo_blink_led.bin", "type": "launch", "command": "${env.COMSPEC}", "args": [ "copy BUILD\\Nucleo_blink_led.bin D:" ] } ] }
デバッグ
Visual StudioからMbedのデバッグは、Visual Studio -> GDB Client(arm-none-eabi-gdb) -> GDB Server -> Mbedデバイスという経路で行われます。
GDB Client(arm-none-eabi-gdb)はVisual StudioオプションのEmbedded開発とIoT開発に含まれています。
GDB Serverはデバイスに合わせて別途インストールしておく必要があります。メジャーところはpyOCD、OpenOCDですね。
今回はST-Linkが搭載されているNUCLEOなので、OpenOCDをつかうことにします。
OpenOCD
いろいろなバリエーションのものがネットで配布されていますが、お友達のkekyoさんがビルドしているものがあるので、それを使いましょう。
リリース1.0.1にあるopenocd-0.10.0_i686-w64-mingw32_2018-01-14.tar.bz2をC:\OpenOCD\openocd-0.10.0に解凍してください。
Debug and Launch Settings
Nucleo_blink_led.binを右クリックしてDebug and Launch Settingsを選んでください。Debugger選択画面が表示されるので、C/C++ Debug microcontroller(gdbserver)を選択すると、マイコンデバッグ用のlaunch.vs.jsonが作られます。
そして、launch.vs.jsonを修正します。
GDB Server
GDB Serverに関するエントリ(3箇所)を変更してください。debugServerArgsとserverStartedはMbedデバイスによって記入内容が違うことがあるのでちょっと難しいです。特にserverStarted。コマンドプロンプトでGDB Serverを起動して、表示された文言をコピーしましょう。
launch.vs.json(GDB Server関連) - 変更前
"debugServerPath": "path-to-your\\gdbserver.exe", "debugServerArgs": "-f path-to-your/board.cfg", "serverStarted": "GDB\\ server\\ started",
launch.vs.json(GDB Server関連) - 変更後
"debugServerPath": "C:\\OpenOCD\\openocd-0.10.0\\bin\\openocd.exe", "debugServerArgs": "-f board\\st_nucleo_f4.cfg", "serverStarted": "Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints",
GDB Client
GDB Clientに関するエントリ(1箇所)を変更してください。デフォルトの記述のままで正しそうですが、現時点はフルパスを明記しないと動かないようです。
launch.vs.json(GDB Client関連) - 変更前
"miDebuggerPath": "${env.gccpath}\\bin\\arm-none-eabi-gdb.exe",
launch.vs.json(GDB Client関連) - 変更後
"miDebuggerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\Preview\\Professional\\Linux\\gcc_arm\\bin\\arm-none-eabi-gdb.exe",
Setup commands
GDBのセットアップコマンドを変更してください。一番最初のエントリはコメントなので削除する必要があります。必要に応じて、追加のコマンドを追記します。
launch.vs.json(セットアップコマンド) - 変更前
"setupCommands": [ { "text": "Documentation: Learn how to configure embedded debugging", "description": "See here for more info http://aka.ms/vsembeddeddebug", "ignoreFailures": true }, { "text": "-environment-cd ${workspaceRoot}/BUILD" }, { "text": "-file-exec-and-symbols ${workspaceRootFolderName}.elf", "description": "load file", "ignoreFailures": false }, { "text": "-enable-pretty-printing", "ignoreFailures": true }
launch.vs.json(セットアップコマンド) - 変更後
"setupCommands": [ { "text": "-environment-cd ${workspaceRoot}/BUILD" }, { "text": "-file-exec-and-symbols ${workspaceRootFolderName}.elf", "description": "load file", "ignoreFailures": false }, { "text": "-enable-pretty-printing", "ignoreFailures": true }, { "text": "monitor reset halt", "ignoreFailures": true }, { "text": "monitor reset init", "ignoreFailures": true }
デバッグ情報の生成
MbedオンラインコンパイラからエクスポートしたMakefileだと、コンパイル時にデバッグ情報が付加されていません。Makefile内のCCとCPPに'-g'を追加、'-Os'を'-O0'に変更してリビルド、デプロイしてください。リビルドですが、Makefile修正だとリビルドされないのでCleanしてBuildしてください。
Makefile(一部) - 変更前
CC = 'arm-none-eabi-gcc' '-std=gnu99' '-c' '-Wall' '-Wextra' '-Wno-unused-parameter' '-Wno-missing-field-initializers' '-fmessage-length=0' '-fno-exceptions' '-fno-builtin' '-ffunction-sections' '-fdata-sections' '-funsigned-char' '-MMD' '-fno-delete-null-pointer-checks' '-fomit-frame-pointer' '-Os' '-mcpu=cortex-m4' '-mthumb' '-mfpu=fpv4-sp-d16' '-mfloat-abi=softfp' CPP = 'arm-none-eabi-g++' '-std=gnu++98' '-fno-rtti' '-Wvla' '-c' '-Wall' '-Wextra' '-Wno-unused-parameter' '-Wno-missing-field-initializers' '-fmessage-length=0' '-fno-exceptions' '-fno-builtin' '-ffunction-sections' '-fdata-sections' '-funsigned-char' '-MMD' '-fno-delete-null-pointer-checks' '-fomit-frame-pointer' '-Os' '-mcpu=cortex-m4' '-mthumb' '-mfpu=fpv4-sp-d16' '-mfloat-abi=softfp'
Makefile(一部) - 変更後
CC = 'arm-none-eabi-gcc' '-g' '-std=gnu99' '-c' '-Wall' '-Wextra' '-Wno-unused-parameter' '-Wno-missing-field-initializers' '-fmessage-length=0' '-fno-exceptions' '-fno-builtin' '-ffunction-sections' '-fdata-sections' '-funsigned-char' '-MMD' '-fno-delete-null-pointer-checks' '-fomit-frame-pointer' '-O0' '-mcpu=cortex-m4' '-mthumb' '-mfpu=fpv4-sp-d16' '-mfloat-abi=softfp' CPP = 'arm-none-eabi-g++' '-g' '-std=gnu++98' '-fno-rtti' '-Wvla' '-c' '-Wall' '-Wextra' '-Wno-unused-parameter' '-Wno-missing-field-initializers' '-fmessage-length=0' '-fno-exceptions' '-fno-builtin' '-ffunction-sections' '-fdata-sections' '-funsigned-char' '-MMD' '-fno-delete-null-pointer-checks' '-fomit-frame-pointer' '-O0' '-mcpu=cortex-m4' '-mthumb' '-mfpu=fpv4-sp-d16' '-mfloat-abi=softfp'
デバッグ
Select Start ItemをNucleo_blink_led.binにしてデバッグ実行すればOKです。
が!デプロイ直後だとうまくブレークできないときがあるようです(あります)。かなり高い確率で。そんなときは、デバッグ停止して、NUCLEOのRESETボタンをクリック、再度、デバッグ実行するとうまく動くようです。思うようにブレークされないときはRESETしましょう(笑
MbedプログラムをVisual Studioでビルドする
前回に続き、MbedプログラムをVisual Studioでビルド(コンパイル)を試してみました。
環境は以下のとおりです。
- Windows 10 64bit 1709
- Visual Studio 2017 15.5.3
- NUCLEO-F401RE
ビルド
試すといっても、Makefileを右クリックしてBuildするだけ...と思いきや、右クリックしてもBuild(やClean)が表示されていません。
Visual Studioのバージョンを上げたり、15.6 Preview 2を入れたりしても、状況変わらず。
試行錯誤した結果、英語表示に切り替えるとBuild/Cleanがでてくることが分かりました。(お、おぅ...)
本件、マイクロソフトへFeedbackしましたので、改善されるでしょう。
気分一新、Makefileを右クリックしてBuildを選ぶと、make.exeが起動しないエラーが。
'C:\mbed\Nucleo_blink_led_gcc_arm_nucleo_f401re\Nucleo_blink_led\Makefile' (Build) Process 'make.exe' failed to start. 指定されたファイルが見つかりません。 at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo) at System.Diagnostics.Process.Start() at Microsoft.VisualStudio.VC.Workspace.MakefileTaskAction.<RunAsync>d__19.MoveNext() Printing diag info: ActionType = Build filepath = C:\mbed\Nucleo_blink_led_gcc_arm_nucleo_f401re\Nucleo_blink_led\Makefile pwd = C:\mbed\Nucleo_blink_led_gcc_arm_nucleo_f401re\Nucleo_blink_led path = C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Linux\gcc_arm\arm-none-eabi\bin;C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Linux\gcc_arm\bin;C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Linux\GNU MCU Eclipse\Build Tools\2.9-20170629-1013\bin\bin makename = make.exe makepath = C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Linux\GNU MCU Eclipse\Build Tools\2.9-20170629-1013\bin makearg = BuildConfiguration = gccarm
わたしのPCでは、C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional に Linux というフォルダーが無いので何かインストールが不足しているんじゃないかと、Visual Studio インストーラーを見たところ、それっぽい項目が増えている?ではありませんか!
C++によるLinux開発 にある、Embedded開発とIoT開発 をチェックして、追加インストールすると、Buildが正常に実行されるようになりました。
gccは6.3.1でした。
C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Linux\gcc_arm\bin>arm-none-eabi-gcc --version arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors 6-2017-q2-update) 6.3.1 20170620 (release) [ARM/embedded-6-branch revision 249437]
MbedプログラムをVisual Studioで編集する(IntelliSense使えるよっ)
twitterで、Visual StudioでArmデバイスのデバッグができるようになったという情報が流れてきました。
Debugging an embedded ARM device in Visual Studio https://t.co/sF2Rn7J0hd
— 雪だるまの人 (@toyowata) 2018年1月11日
Visual Studio 2017 15.5でARM GCCをサポート、15.6 Preview 2でデバッグが可能になったみたい。これは素晴らしい。
というわけで、こちらに記載の、編集作業を試してみました。
全体を、編集、ビルド、フラッシュ、デバッグの4つと考え、今回は編集を試しました。
環境は以下のとおりです。(編集だけなら関係ないことですが)NUCLEO-F411REが手元になかったのでNUCLEO-F401REをターゲットにしました。
- Windows 10 64bit 1709
- Visual Studio 2017 15.5.2
- NUCLEO-F401RE
プログラムの作成
プログラムはMbedオンラインコンパイラで作成します。Visual Studioで新規作成するのではなく、Mbedオンラインコンパイラで新規作成したものをエクスポートして、それをVisual Studioの「フォルダを開く」で開きます。
NUCLEO-F401REのプログラム作成 in Mbedオンラインコンパイラ
Mbedオンラインコンパイラで、新しいプログラムを作成します。プラットフォームはNUCLEO-F401RE。テンプレートは参考ブログと同じBlinky LED test for the ST Nucleo boardsにしました。
Lチカのコードが入ったmain.cppとmbed 2.0ライブラリのプログラムが出来上がります。
エクスポート in Mbedオンラインコンパイラ
出来上がったプログラムを、プログラムのエクスポートでエクスポートします。Export Toolchainにたくさん選択肢があって迷いますが、参考ブログのとおりGC(ARM Embedded)を選びました。
すると、プログラムがダウンロードされるので適当なフォルダに解凍します。ダウンロードされたファイルには、main.cppやmbedライブラリに加え、MakefileやGCC_ARMに対応するためのファイル?が含まれています。
Visual Studioで開く
Visual Studioの「フォルダを開く」機能で、エクスポートしたプログラムを開きます。デフォルトではIntelliSenseがうまく機能しないので、CppProperties.jsonを作成、変更して対処します。
フォルダを開く in Visual Studio
Visual Studioを起動して、ファイル->開く->フォルダーでプログラムの置いてあるフォルダを開きます。すると、ソリューションエクスプローラーにファイルが表示されます。
この時点では、ARM GCCに対応していない状況なので、main.cppを開くとファイル参照や名前参照が解決できず、いくつか赤波線が表示されてしまいます。
CppProperties.jsonを編集(NG) in Visual Studio
プロジェクト->設定の編集->CppProperties.jsonを選ぶと、CppProperties.jsonが作られます。自動的にいくつかの設定が記入されていますが、すべて消して、下記を記入、保存します。
CppProperties.json
{ "configurations": [ { "inheritEnvironments": [ "gcc-arm" ], "name": "gccarm", "includePath": [ "${env.INCLUDE}" ], "defines": [ ] } ] }
何故かエラー!?
C:\mbed\Nucleo_blink_led_gcc_arm_nucleo_f401re\Nucleo_blink_led\CppProperties.json: 警告: 環境変数 '${env.INCLUDE}' を評価できませんでした。 C:\mbed\Nucleo_blink_led_gcc_arm_nucleo_f401re\Nucleo_blink_led\CppProperties.json: 警告: 環境変数 '${cpp.intelliSenseMode}' を評価できませんでした。
main.cppの赤波線が消えません。悲しい。
CppProperties.jsonを編集(OK) in Visual Studio
試行錯誤したところ、どうやら参考ブログに書かれているinheritEnvironmentsの記述を変更すると、赤波線が消えました。
CppProperties.json
{ "configurations": [ { "inheritEnvironments": [ "gcc_arm" ], "name": "gccarm", "includePath": [ "${env.INCLUDE}" ], "defines": [ ] } ] }
結果
IntelliSense、バッチリ機能します!!
C標準ライブラリの名前解決ができないようなので引き続き調べたいと思います。(includePathに追加かと)
inheritEnvironmentsの記述ですが、Visual Studio 15.5はgcc_arm, 15.6 Preview 2はgcc-armでした。
M5StackのTimed outエラー対策
一目惚れのM5Stack、購入してから〇ヵ月経ってしまいましたが、年末年始に時間がとれたので動かしてみました。
見た目がカッコイイ、M5Stack
5cm角のコアモジュールに、さまざまな機能モジュールを積み上げて機能拡張できる、開発ツールです。
液晶、スイッチ、USBコネクター、マイクロSDスロット、Groveコネクターがコンパクトで綺麗なケースに包まれています。見た目大事。当初、MPUはESP8266だったようですが、現在発売されているのはESP32で、工事設計認証も取得済みのようです。
AliexpressのM5Storeから購入できます。
開発環境はArduino IDE
Getting Startedに沿って実施しました。
開発環境は、Arduino IDE + Espressif ESP32という、一般的な構成。そして、M5Stack用ライブラリを追加、利用する形です。
開発の仕方については、ドキュメントがほとんど見当たりませんでした。ただ、サンプルスケッチが多数用意されているので、動かしてみてコード読みなさいという感じなのかもしれません。
スケッチのコンパイル、書き込み
サンプルのMPU9250BasicAHRSをコンパイル、書き込みしてみました。
コンパイルは3分ほど。結構、遅いですね。ESP32はこれくらいかかるのが一般的なのだろうか。まぁ、問題はありません。ちゃんとコンパイルできました。
書き込みは... Timed outエラーが発生して書き込みできず。何度試してもダメ。悲しい。
esptool.py v2.1 Connecting........_____....._____....._____....._____....._____....._____....._____....._____....._____....._____ A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
Tips - コンデンサを繋ぐ
M5Stack Communityに同様の事例と対策が載っていたので、手元にあった4.7uFをRSTとGNDに接続してみたところ、きちんと書き込みできました。
コンデンサを内蔵
せっかく恰好いいケースなのにコンデンサがはみ出ているのは悲しいので、分解して基板上に4.7uFのチップコンデンサを実装しました。
Azure IoT HubとDeviceの通信
公式ドキュメントを読んで机上で整理したものなので、実際の動作と異なる可能性があります。
IoT HubのエンドポイントはDevice, ServiceとManagementに関するものがあります。
このうちのAzure IoT HubとDeviceの通信に使用する、Deviceのエンドポイントを整理しました。(上図の左側)
Device to Cloud
DeviceからCloud(IoT Hub)に情報を送信する手段は、3つ用意されています。
メッセージ
- 時系列データやアラートの送信に使用します。
- エンドポイントは/devices/{deviceId}/messages/events。
- IoT Hubに最大7日間、保存することができます。
- 1つのメッセージは最大256KB。
レポートプロパティ(報告プロパティ)
- 動作状態の送信に使用します。
- エンドポイントは$iothub/twin/PATCH/properties/reported/?$rid={request id}。
- IoT Hubのデバイスツインに保存。
- レポートプロパティは最大8KB。
ファイルのアップロード
- 大きなデータの送信に使用します。
- IoT Hubにファイルのアップロード要求を送信してから、Azure Storage SDKでファイルをアップロードします。
- Azure Blob Storageに保存。
- ファイルの最大はAzure Blob Storageによって制限されます。
Cloud to Device
Cloud(IoT Hub)からDeviceに情報を受信する手段は、3つ用意されています。
メッセージ
- IoT Hubに溜まっているメッセージを受信します。
- エンドポイントはdevices/{device_id}/messages/devicebound/#。
- IoT Hubに最大48時間、保存することができます。
- 1つのメッセージは最大64KB。
デザイアープロパティ(必要プロパティ)
- 動作指示設定値の受信に使用します。
- エンドポイントは$iothub/twin/PATCH/properties/desired/?$version={new version}。
- IoT Hubのデバイスツインに保存。
- デザイナープロパティは最大8KB。
ダイレクトメソッド
- 即時指示の受信に使用します。
- エンドポイントは$iothub/methods/POST/#。
- 最大8KB。
azure-c-shared-utility
Azure C SDKの土台となる、azure-c-shared-utilityをビルドしてみました。
リポジトリをclone
Setupのとおり、--recursiveオプションを付けてgit cloneします。
C:\Users\takashi\Documents\github>git clone --recursive https://github.com/Azure/azure-c-shared-utility.git Cloning into 'azure-c-shared-utility'... remote: Counting objects: 15474, done. ... Submodule path 'testtools/umock-c/deps/testrunner': checked out 'f73e0a91e295fb64b94d72aaf16fa54d3079be22' C:\Users\takashi\Documents\github>
何事も無く成功。約23MB。
参照しているサブモジュールは5つでした。
Submodule 'testtools/ctest' (https://github.com/Azure/azure-ctest.git) registered for path 'testtools/ctest' Submodule 'testtools/testrunner' (https://github.com/Azure/azure-c-testrunnerswitcher.git) registered for path 'testtools/testrunner' Submodule 'testtools/umock-c' (https://github.com/Azure/umock-c.git) registered for path 'testtools/umock-c' Submodule 'deps/azure-ctest' (https://github.com/Azure/azure-ctest.git) registered for path 'testtools/umock-c/deps/ctest' Submodule 'deps/testrunner' (https://github.com/Azure/azure-c-testrunnerswitcher.git) registered for path 'testtools/umock-c/deps/testrunner'
ビルド準備
cmakeを実行します。
C:\Users\takashi\Documents\github>cd azure-c-shared-utility C:\Users\takashi\Documents\github\azure-c-shared-utility>cmake .. CMake Error: The source directory "C:/Users/takashi/Documents/github" does not appear to contain CMakeLists.txt. Specify --help for usage, or press the help button on the CMake GUI. C:\Users\takashi\Documents\github\azure-c-shared-utility>
エラーになりました。CMakeLists.txtが無いって。そりゃそうですよ、一つ上の階層はcloneしていませんから。ドキュメントが間違っているのかな。
気を取り直して、cloneしたフォルダでcmakeを実行します。
C:\Users\takashi\Documents\github\azure-c-shared-utility>cmake . -- Building for: Visual Studio 15 2017 -- The C compiler identification is MSVC 19.12.25831.0 -- The CXX compiler identification is MSVC 19.12.25831.0 -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.12.25827/bin/Hostx86/x86/cl.exe -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.12.25827/bin/Hostx86/x86/cl.exe -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.12.25827/bin/Hostx86/x86/cl.exe -- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.12.25827/bin/Hostx86/x86/cl.exe -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Looking for include file stdint.h -- Looking for include file stdint.h - found -- Looking for include file stdbool.h -- Looking for include file stdbool.h - found -- target architecture: x86 -- Performing Test CXX_FLAG_CXX11 -- Performing Test CXX_FLAG_CXX11 - Success -- Configuring done -- Generating done -- Build files have been written to: C:/Users/takashi/Documents/github/azure-c-shared-utility C:\Users\takashi\Documents\github\azure-c-shared-utility>
Visual Studio 15 2017向けのものをMSVCでコンパイルするよう準備したようです。
どこに何が出来上がっているのか分からないのですが、トップフォルダにこれらのファイルが出来上がっていました。
ビルド
cmake --buildを実行します。
C:\Users\takashi\Documents\github\azure-c-shared-utility>cmake --build . .NET Framework 向け Microsoft (R) Build Engine バージョン 15.5.180.51428 Copyright (C) Microsoft Corporation.All rights reserved. 2017/12/24 12:09:57 にビルドを開始しました。 ノード 1 上のプロジェクト "C:\Users\takashi\Documents\github\azure-c-shared-utility\ALL_BUILD.vcxproj" (既定のターゲット)。 ... ビルドに成功しました。 0 個の警告 0 エラー 経過時間 00:00:13.54 C:\Users\takashi\Documents\github\azure-c-shared-utility>
Debugフォルダのaziotsharedutil.libがビルド結果のようです。
Azure IoT HubのSASトークンについて
Azure IoT SDKsを使わずに、Azure IoT HubにMQTT, AMQP, HTTPSなどで接続するにはSASトークンという文字列を渡さなければいけないのだが、このSASトークンが一体何者か良く分からない。
何度、ドキュメントを読み返しても分からない。
さまざまな用語が出てきます。共有アクセスポリシー、セキュリティ資格情報、資格情報、トークン、対称キー、SASトークン、IoTHubセキュリティトークン、セキュリティトークン、共有アクセスキーで署名されたトークン...
あー、わけわからない。
わからないままでは前に進めないので、ちょっと時間をかけて自分なりに整理してみました。
前提
- デバイスからIoT Hub、サービスからIoT Hubに接続するときの、SASトークンを調べました。他のAzureサービスのSASトークンが同様かは不明です。
- IoT Hubへのアクセスの制御の日本語と英語を何度も読み返して整理しました。また、Azureポータルの画面も確認しました。アプリを作って検証とかはしていないです。
デバイスからIoT Hub
IoT Hubレベルで定義されている共有アクセスポリシー、もしくは、デバイス毎のセキュリティ資格情報でアクセス制御します。
デバイス毎のセキュリティ資格情報は、対称キー、自己X509証明書、証明機関X509証明書の3つがあり、デバイスを作るときに指定します。(なお、デバイス毎のセキュリティ資格情報はIoT HubのIdentity Registryに格納されています。)
- 共有アクセスポリシー(IoT Hubレベル)
- セキュリティ資格情報(デバイス毎)
- 対称キー
- 自己X509証明書
- 証明機関X509証明書
このうち、共有アクセスポリシーと対称キーでアクセス制御するときに、SASトークンを生成して、MQTTなどで接続するときに渡します。
サービスからIoT Hub
共有アクセスポリシーでアクセス制御します。おしまいw
共有アクセスポリシーからSASトークンを生成
リソースURIと共有アクセスポリシー名、共有アクセスキー、有効期限から、base64とかHMAC-SHA256計算とかして作り出します。
- リソースURI ... 接続するIoT HubのリソースURI。"myhub.azure-devices.net/devices/device1"
- 共有アクセスポリシー名 ... "device"
- 共有アクセスキー ... "Rosx8/5Q7THau334G6WlwAR0lsZc3Yt1QdcWCmr7KYA="
- 有効期限 ...
適当に適切に決める
共有アクセスポリシー名、共有アクセスキーは、Azureポータルの下図の箇所の値です。
計算の具体的なコードはドキュメントをgenerateSasTokenで検索して探してください。
対称キーからSASトークンを生成
リソースURIと対称キー、有効期限から、base64とかHMAC-SHA256計算とかして作り出します。
- リソースURI ... 接続するIoT HubのリソースURI。"myhub.azure-devices.net/devices/device1"
- 対称キー ... "HDBqV7U2dRosEh2Xxf//MYzA2T111rRkEmV2dJW0k0s="
- 有効期限 ...
適当に適切に決める
対称キーは、Azureポータルの下図の箇所の値です。
計算の具体的なコードはドキュメントをgenerateSasTokenで検索して探してください。
気になったこと
- ”トークンの期限が切れた時点で、IoT Hub はデバイスの接続を切断します。 ”という記述があります。なので、切断されたら自動的にSASトークンを再生成して、ネットワーク再接続するロジックが必要。
- 最後の方にちょろっと書いてある、”カスタムデバイスの認証”モデルが気になる。デバイスはトークンサービスにSASトークンを要求すると、何らかの手段でデバイスを認証してSASトークンを発行する仕組み。
- 共有アクセスポリシーや対称キー(から生成したSASトークン)はアクセスの制御。認証ではない!ところがポイント。