MbedプログラムをVisual Studioでデバッグする

前回に続き、MbedプログラムをVisual Studioデバッグしてみました。

元ネタはこちらです。 blogs.msdn.microsoft.com

元ネタにあるとおり、デバッグができるのはPreviewのVisual Studio 2017 15.6です。そのため、前回と違ってVisual Studio 2017 Previewを使いました。Visual Studio 2017 Previewはここからダウンロードできます。

プログラムの作成

前々回と同じです。

Embedded開発とIoT開発をインストール

Visual Studioに含まれている、Visual C++ tools for CMake and LinuxEmbedded開発とIoT開発のオプションをインストールしておく必要があります。

f:id:matsujirushix:20180203233230p:plain

Visual Studioを英語表示にしておく

前回Visual Studioを英語表示にしておかないとBuild/Cleanのコンテキストメニューが表示されなかったので、早めに英語表示にしておきます。ツール -> オプション国際対応の設定にある言語をEnglishにして、Visual Studioを再起動してください。

f:id:matsujirushix:20180203223718p:plain

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負荷が気になる場合はしばらく放置しましょう。

f:id:matsujirushix:20180203230914p:plain

ビルド

前回と同じです。

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:"
      ]
    }
  ]
}

f:id:matsujirushix:20180203232116p:plain

デバッグ

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さんがビルドしているものがあるので、それを使いましょう。

github.com

リリース1.0.1にあるopenocd-0.10.0_i686-w64-mingw32_2018-01-14.tar.bz2をC:\OpenOCD\openocd-0.10.0に解凍してください。

f:id:matsujirushix:20180204211317p:plain

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.jsonGDB Server関連) - 変更前

"debugServerPath": "path-to-your\\gdbserver.exe",
"debugServerArgs": "-f path-to-your/board.cfg",
"serverStarted": "GDB\\ server\\ started",

launch.vs.jsonGDB 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.jsonGDB Client関連) - 変更前

"miDebuggerPath": "${env.gccpath}\\bin\\arm-none-eabi-gdb.exe",

launch.vs.jsonGDB 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です。

f:id:matsujirushix:20180204215915p:plain

が!デプロイ直後だとうまくブレークできないときがあるようです(あります)。かなり高い確率で。そんなときは、デバッグ停止して、NUCLEOのRESETボタンをクリック、再度、デバッグ実行するとうまく動くようです。思うようにブレークされないときはRESETしましょう(笑

f:id:matsujirushix:20180204215832p:plain

MbedプログラムをVisual Studioでビルドする

前回に続き、MbedプログラムをVisual Studioでビルド(コンパイル)を試してみました。

blogs.msdn.microsoft.com

環境は以下のとおりです。

ビルド

試すといっても、Makefileを右クリックしてBuildするだけ...と思いきや、右クリックしてもBuild(やClean)が表示されていません。

f:id:matsujirushix:20180114183421p:plain

Visual Studioのバージョンを上げたり、15.6 Preview 2を入れたりしても、状況変わらず。

試行錯誤した結果、英語表示に切り替えるとBuild/Cleanがでてくることが分かりました。(お、おぅ...)

f:id:matsujirushix:20180114190613p:plain

本件、マイクロソフトへ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 インストーラーを見たところ、それっぽい項目が増えている?ではありませんか!

f:id:matsujirushix:20180114200216p:plain

C++によるLinux開発 にある、Embedded開発とIoT開発 をチェックして、追加インストールすると、Buildが正常に実行されるようになりました。

f:id:matsujirushix:20180114200407p:plain

f:id:matsujirushix:20180114200447p:plain

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デバイスデバッグができるようになったという情報が流れてきました。

Visual Studio 2017 15.5でARM GCCをサポート、15.6 Preview 2でデバッグが可能になったみたい。これは素晴らしい。

というわけで、こちらに記載の、編集作業を試してみました。

blogs.msdn.microsoft.com

全体を、編集、ビルド、フラッシュ、デバッグの4つと考え、今回は編集を試しました。

環境は以下のとおりです。(編集だけなら関係ないことですが)NUCLEO-F411REが手元になかったのでNUCLEO-F401REをターゲットにしました。

プログラムの作成

プログラムはMbedオンラインコンパイラで作成します。Visual Studioで新規作成するのではなく、Mbedオンラインコンパイラで新規作成したものをエクスポートして、それをVisual Studioの「フォルダを開く」で開きます。

NUCLEO-F401REのプログラム作成 in Mbedオンラインコンパイラ

Mbedオンラインコンパイラで、新しいプログラムを作成します。プラットフォームはNUCLEO-F401RE。テンプレートは参考ブログと同じBlinky LED test for the ST Nucleo boardsにしました。

f:id:matsujirushix:20180114124653p:plain

Lチカのコードが入ったmain.cppとmbed 2.0ライブラリのプログラムが出来上がります。

f:id:matsujirushix:20180114124909p:plain

エクスポート in Mbedオンラインコンパイラ

出来上がったプログラムを、プログラムのエクスポートでエクスポートします。Export Toolchainにたくさん選択肢があって迷いますが、参考ブログのとおりGC(ARM Embedded)を選びました。

f:id:matsujirushix:20180114125104p:plain

f:id:matsujirushix:20180114125220p:plain

すると、プログラムがダウンロードされるので適当なフォルダに解凍します。ダウンロードされたファイルには、main.cppやmbedライブラリに加え、MakefileGCC_ARMに対応するためのファイル?が含まれています。

f:id:matsujirushix:20180114125944p:plain

f:id:matsujirushix:20180114125922p:plain

Visual Studioで開く

Visual Studioの「フォルダを開く」機能で、エクスポートしたプログラムを開きます。デフォルトではIntelliSenseがうまく機能しないので、CppProperties.jsonを作成、変更して対処します。

フォルダを開く in Visual Studio

Visual Studioを起動して、ファイル->開く->フォルダーでプログラムの置いてあるフォルダを開きます。すると、ソリューションエクスプローラーにファイルが表示されます。

この時点では、ARM GCCに対応していない状況なので、main.cppを開くとファイル参照や名前参照が解決できず、いくつか赤波線が表示されてしまいます。

f:id:matsujirushix:20180114130117p:plain

f:id:matsujirushix:20180114130321p:plain

CppProperties.jsonを編集(NG) in Visual Studio

プロジェクト->設定の編集->CppProperties.jsonを選ぶと、CppProperties.jsonが作られます。自動的にいくつかの設定が記入されていますが、すべて消して、下記を記入、保存します。

f:id:matsujirushix:20180114130410p:plain

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}' を評価できませんでした。

f:id:matsujirushix:20180114133712p:plain

main.cppの赤波線が消えません。悲しい。

CppProperties.jsonを編集(OK) in Visual Studio

試行錯誤したところ、どうやら参考ブログに書かれているinheritEnvironmentsの記述を変更すると、赤波線が消えました。

(誤)gcc-arm -> (正)gcc_arm

CppProperties.json

{
  "configurations": [
    {
      "inheritEnvironments": [
        "gcc_arm"
      ],
      "name": "gccarm",
      "includePath": [
        "${env.INCLUDE}"
      ],
      "defines": [

      ]
    }
  ]
}

結果

IntelliSense、バッチリ機能します!!

f:id:matsujirushix:20180114133836p:plain

C標準ライブラリの名前解決ができないようなので引き続き調べたいと思います。(includePathに追加かと)

inheritEnvironmentsの記述ですが、Visual Studio 15.5はgcc_arm, 15.6 Preview 2はgcc-armでした。

M5StackのTimed outエラー対策

一目惚れのM5Stack、購入してから〇ヵ月経ってしまいましたが、年末年始に時間がとれたので動かしてみました。

見た目がカッコイイ、M5Stack

5cm角のコアモジュールに、さまざまな機能モジュールを積み上げて機能拡張できる、開発ツールです。

f:id:matsujirushix:20180107143951p:plain

液晶、スイッチ、USBコネクター、マイクロSDスロット、Groveコネクターがコンパクトで綺麗なケースに包まれています。見た目大事。当初、MPUはESP8266だったようですが、現在発売されているのはESP32で、工事設計認証も取得済みのようです。

AliexpressのM5Storeから購入できます。

f:id:matsujirushix:20180107152509p:plain

開発環境は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

f:id:matsujirushix:20180107151229p:plain

Tips - コンデンサを繋ぐ

M5Stack Communityに同様の事例と対策が載っていたので、手元にあった4.7uFをRSTとGNDに接続してみたところ、きちんと書き込みできました。

f:id:matsujirushix:20180107151724p:plain

f:id:matsujirushix:20180107151812p:plain

コンデンサを内蔵

せっかく恰好いいケースなのにコンデンサがはみ出ているのは悲しいので、分解して基板上に4.7uFのチップコンデンサを実装しました。

f:id:matsujirushix:20180107152040p:plain

f:id:matsujirushix:20180107152308p:plain

Azure IoT HubとDeviceの通信

公式ドキュメントを読んで机上で整理したものなので、実際の動作と異なる可能性があります。

IoT HubのエンドポイントはDevice, ServiceとManagementに関するものがあります。

f:id:matsujirushix:20171230211711p:plain

このうちの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でコンパイルするよう準備したようです。

どこに何が出来上がっているのか分からないのですが、トップフォルダにこれらのファイルが出来上がっていました。

f:id:matsujirushix:20171224120843p:plain

ビルド

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がビルド結果のようです。

f:id:matsujirushix:20171224123111p:plain

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で検索して探してください。

f:id:matsujirushix:20171223232322p:plain

対称キーからSASトークンを生成

リソースURIと対称キー、有効期限から、base64とかHMAC-SHA256計算とかして作り出します。

  • リソースURI ... 接続するIoT HubのリソースURI。"myhub.azure-devices.net/devices/device1"
  • 対称キー ... "HDBqV7U2dRosEh2Xxf//MYzA2T111rRkEmV2dJW0k0s="
  • 有効期限 ... 適当に適切に決める

対称キーは、Azureポータルの下図の箇所の値です。

計算の具体的なコードはドキュメントgenerateSasTokenで検索して探してください。

f:id:matsujirushix:20171223232843p:plain

気になったこと

  • トークンの期限が切れた時点で、IoT Hub はデバイスの接続を切断します。 ”という記述があります。なので、切断されたら自動的にSASトークンを再生成して、ネットワーク再接続するロジックが必要。
  • 最後の方にちょろっと書いてある、”カスタムデバイスの認証”モデルが気になる。デバイストークンサービスにSASトークンを要求すると、何らかの手段でバイスを認証してSASトークンを発行する仕組み。
  • 共有アクセスポリシーや対称キー(から生成したSASトークン)はアクセスの制御。認証ではない!ところがポイント。

参考