Azure IoT HubとAzure IoT Edge、各SDKの位置づけ

Build 2017 Keynoteにも挙がっていた、Azure IoT Edge。

channel9.msdn.com

Stream AnalyticsやMachine Learningをエッジ側で動作させようというもので、とても興味深いものですが、そのAzure IoT Edgeを詳しく解説するイベントがあったので参加しました。

algyan.connpass.com

タイトルが「Deep Deep Dive」とDeepが2回w

マイクロソフト太田さんが2時間休憩なしで説明しまくるという、結構ハードなイベントでした。

イベントの内容は後日資料、動画が公開される予定なので、それを見てもらうとして、、、

イベントの後に、某氏から「EdgeとかDevice SDKとかの関係が良く分からない。」と聞かれたので、復習&整理しておこうと思い、ブログ書くことにしました。

Azure IoT Hub

現在、マイクロソフトはデバイスをAzureに接続する手段として、Azure IoT Hubを提供しています。下図のとおり、デバイスとバックエンドを仲介&スケーリングすることで、何百万台ものデバイスの同時接続することができます。

f:id:matsujirushix:20170902211748p:plain 画像元リンク

Azure IoT Hubとデバイスの接続

上図の左側にあたる、デバイスからAzure IoT Hubへの接続は、具体的にはAMQPやMQTT、HTTPで接続、通信するのですが、さまざまなデバイスで容易に接続できるよう、いくつものOS、言語でAzure IoT Hubに接続するライブラリが提供されています。これをAzure IoT Hub device SDKといいます。

Azure IoT Hubとバックエンドの接続

上図の右側にあたる、Azure IoT Hubからバックエンドへの接続は、Azure IoT Hub service SDKが提供されています。

Azure IoT HubとDevice SDKの位置づけ

図示するとこのような位置づけで、Azure IoT Hub device SDKは"device"という名称が付いているものの、全てのデバイスに入れるものではなく、Azure IoT Hubに接続するデバイスで使用するものです。

f:id:matsujirushix:20170902215615p:plain画像元リンク(一部変更)

省電力デバイス -> 〇〇〇 -> Azure IoT Hub

Azure IoT Hubへの接続にはAzure IoT Hub device SDKを使うことは分かりましたが、BLEデバイスなどの極めて省電力なデバイスでこれらの機能(実際はAMQPなど)を載せるのは不可能です。このようなときは、ゲートウェイを設置して、省電力デバイスの代わりにAzure IoT Hubへ接続を代行します。このゲートウェイを実装するために、Azure IoT Gateway SDKというものが提供されています。(いました)

ゲートウェイからエッジに

バックエンドで実行していた分析をオフラインでも実行したい、とか、通信コストを削減したいというニーズが高まり、それに伴いバックエンドの機能をデバイスの近くで実行するためのコンセプトが発表されました。それがAzure IoT Edgeです。

実体は、前述のAzure IoT Gateway SDKAzure IoT Edgeと改名して、そこに機能拡張が進められています。

下図のように、現状はまだゲートウェイ+αですが、順次整備されていくものと思います。

f:id:matsujirushix:20170902223613p:plain 画像元リンク

まとめ

  • 直接、Azure IoT Hubまで到達できるデバイスは、Azure IoT Hub device SDKを使う。
  • 直接、Azure IoT Hubに到達できないデバイス、省電力デバイスなどは、Azure IoT Edgeを経由して、Azure IoT Hubへ接続。

f:id:matsujirushix:20170902222643p:plain

各ライブラリ、コードの所在は以下のとおりです。

  - Azure IoT SDK for C

    - Azure IoT Hub device SDK for C

    - Azure IoT Hub service SDK for C

  - Azure IoT SDK for .NET

    - Azure IoT device SDK for .NET

    - Azure IoT service SDK for .NET

  - ...

MakeCode for micro:bitをローカル環境で立ち上げる

micro:bitのソースを少しイジってみようと思い、pxt-microbitソースから環境を構築してみたのですが、思っていた以上に辛かったので書き留めました。

ラズパイにOSをインストール

こちらを参考に、RaspberryPi3にRaspbianをインストールします。

最新のRaspbianイメージ(2017-08-16-raspbian-stretch.img)では、途中のコンパイルでエラーになり回避できない(できなかった)ので、少し古いRaspbianイメージ(2017-07-05-raspbian-jessie.img)を使ってください。

uepon.hatenadiary.com

初期設定は、WiFi接続とSSHを有効化、タイムゾーン、キーボードを変更しました。

タイムゾーンAsia/Tokyo

キーボード … Japanese (PC-98xx Series)

pxt-microbitをソースから構築

こちらのgithub上のソースから構築した場合」を参考にしました。

takafuminaka.blogspot.jp

前準備

pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get upgrade

Nodeをインストール

こちらにあるコマンドのとおり、Node.js 8をインストールします。

pi@raspberrypi:~ $ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
pi@raspberrypi:~ $ sudo apt-get install -y nodejs

インストール後のバージョンはこちら。

pi@raspberrypi:~ $ node -v
> v8.4.0

yottaをインストール

こちらにあるコマンドのとおり、yottaをインストールします。

pi@raspberrypi:~ $ sudo apt-get update && sudo apt-get install python-setuptools cmake build-essential ninja-build python-dev libffi-dev libssl-dev && sudo easy_install pip
pi@raspberrypi:~ $ sudo pip install yotta

インストール後のバージョンはこちら。

pi@raspberrypi:~ $ yotta --version
> 0.18.2

toolchainをインストール

GNU ARM Embedded Toolchainをインストールします。

pi@raspberrypi:~ $ sudo apt-get install gcc-arm-none-eabi

インストール後のバージョンはこちら。

pi@raspberrypi:~ $ arm-none-eabi-gcc --version
> arm-none-eabi-gcc (4.8.4-1+11-1) 4.8.4 20141219 (release)

最新のRaspbianイメージ(2017-08-16-raspbian-stretch.img)だと、arm-none-eabi-gcc (15:4.9.3+svn231177-1) 4.9.3 20150529 (prerelease)がインストールされるのですが、4.9.3だと後にコンパイルエラーが発生しました。少し古いRaspbianイメージ(2017-07-05-raspbian-jessie.img)だと、arm-none-eabi-gcc (4.8.4-1+11-1) 4.8.4 20141219 (release)がインストールされて、コンパイルエラーが発生しませんでした。

追加でパッケージをインストール

npm installで発生するエラーを回避するために、不足しているパッケージをインストールします。

Package gnome-keyring-1 was not foundの対策

pi@raspberrypi:~/pxt-microbit $ sudo apt-get install libgnome-keyring-dev

libusb.h: No such file or directoryの対策

pi@raspberrypi:~/pxt-microbit $ sudo apt-get install libusb-1.0-0-dev

/bin/sh: 1: srec_cat: not foundの対策

pi@raspberrypi:~/pxt-microbit $ sudo apt-get install srecord

pxt

あとはこちらの手順とおり。

pxt-microbitソースをcloneして、

pi@raspberrypi:~ $ git clone https://github.com/Microsoft/pxt-microbit
pi@raspberrypi:~ $ cd pxt-microbit

PXT command line toolsをインストール。

pi@raspberrypi:~/pxt-microbit $ sudo npm install -g pxt

依存ファイルをインストール。

pi@raspberrypi:~/pxt-microbit $ npm install

hostnameのlocalhostIPアドレスに書き換えてから、

pi@raspberrypi:~/pxt-microbit $ vi ~/pxt-microbit/node_modules/pxt-core/built/server.js

pxt-microbitを起動します。

pi@raspberrypi:~/pxt-microbit $ pxt serve

最後に

最新のRaspbianイメージで構築できなかったのは心残り。

stretchにarm-none-eabi-gcc 4.8を入れるとか、pxt-microbitをarm-none-eabi-gcc 4.9でビルドできるようにするとか。

上記手順をAzure仮想マシンでも確認したところ、pxt serveまでは正常に動くことが確認できた。現時点のやり方としては問題なさそう。(Azure仮想マシンの受信規則を変更しなかったので、ブラウザからpxtエディタが動作するところまでは確認していません。えへ。)

TinyCLR OS 環境構築方法(NUCLEO-F401RE)メモ

.NET MicroFrameworkが実質開発ストップしていますが、GHI Electronicsが分岐してシンプルにして(?)TinyCLR OSとして整備しているようです。

まだアルファ版ではありますが、現在公開されているTinyCLR OSの環境構築が上手くできたので、手順を書き留めておきます。

TinyCLRは未だアルファ版なので、リンクが切れたり手順が変更になったりする可能性があります。ご了承ください。

わたしの環境

作業前の、わたしのパソコン環境は次のとおりです。

akizukidenshi.com

Windowsデバイスドライバをインストール

NUCLEO-F401REのVirtual COMが認識されていない場合は、ここにあるデバイスドライバをインストールします。

f:id:matsujirushix:20170813152513p:plain

VisualStudio拡張をインストール

ここにあるGHIElectronics.TinyCLR.VisualStudio.0.5.0.vsixをインストールします。

ファームウェアをデバイスにインストール

ここにあるNUCLEO-F401RE Firmware.0.5.1.binをNUCLEO-F401REのmbedドライブにコピーします。

アプリケーションを作って動かす

基本、これ。

ただし、下記2点が違います。

  • プロジェクトのプロパティでSerial接続にしてください。

  • NUCLEO-F401REをUSB接続する都度、ここにあるComInit.exeを実行してVirtual COMを設定変更する必要があります。(変更しないと、VisualStudioから接続できない)

matsujirushi.hatenablog.jp

f:id:matsujirushix:20170813153454p:plain

Tiny CLR OSが対応するボードのMPU

ボードの購入や、ポーティングの参考になればと思い、Tiny CLR OSが対応しているボードのMPUについて調べてみました。

対象はTinyCLR-PortsのDevices配下にあるもの。

FEZ

Arduinoピン互換のボードです。

カタログサイトには、"FEZ"という名前のArduinoフォームファクタが3つあり、どれを指しているのか分かりません。

f:id:matsujirushix:20170802213648p:plain

それぞれのボードの回路図を見ると、FEZ LemurはSTM32F40x、FEZ Panda IIIはSTM32F427XX、FEZ Cobra IIIはLPC1788でした。(FEZ Cobra IIIはG120モジュールが載っていて、G120モジュールのデータシートから分かりました。)

docsのmbedについて書いてあるところにNucleo-F401REと同じMPUと書いてあるので、ボードはFEZ LemurSTM32F401と思われます。

FEZCerberus

.NET Gadgeteerのボードです。

f:id:matsujirushix:20170802220035p:plain

回路図を見ると、MPUはSTM32F40X。

tinyclr.jpによるとSTM32F405らしい。

G30

チップ単体の製品。SoCというカテゴリーのようです。

f:id:matsujirushix:20170802220642p:plain

データシートによると、STM32F401

G80

G30と同様、SoC。

f:id:matsujirushix:20170802220733p:plain

データシートによると、STM32F427

Netduino 3

Arduinoピン互換でありながら、.NET Gadgeteerも接続できるボードです。

f:id:matsujirushix:20170802221727p:plain

回路図を見ると、STM32F427

Quail

mikro BUSのボードです。(これ初めて知りました。)

f:id:matsujirushix:20170803084734p:plain

mikro BUSに接続できるモジュールはClick Boardsらしく、すでに大量のモジュールが販売されています。

shop.mikroe.com

Specificationによると、STM32F427

まとめ

ボード MPU
FEZ STM32F401
FEZcerberus STM32F405
G30 STM32F401
G80 STM32F427
Netduino3 STM32F427
Quail STM32F427

TinyCLR OS ファームウェアビルド手順

環境構築して、デジタル出力の次は、デジタル入力…が普通だと思いますが、めっちゃポーティング欲が出てきているので、そっちへ向かいましょう!

kotobank.jp

やり方は、Porting TinyCLRに簡潔に書かれています。これにそってやりたいと思います。

TinyCLRをクローン

githubに挙がっているTinyCLRをローカルにcloneします。

git clone https://github.com/ghi-electronics/TinyCLR-Ports

f:id:matsujirushix:20170730215839p:plain

GCCをインストー

GNU ARM Embedded ToolchainからGCCをダウンロード、インストールします。

今回は、gcc-arm-none-eabi-6-2017-q2-update-win32.exeをダウンロードして、起動することでインストールします。

f:id:matsujirushix:20170730220529p:plain

デフォルトだと、C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q2-update フォルダにインストールされます。

f:id:matsujirushix:20170730220850p:plain

CMSISを配置

ARM.CMSIS.4.3.0.packをダウンロードして、拡張子を.zipに変更、中身をTinyCLRのCMSIS配下に配置します。

ARM.CMSIS.4.3.0.packには、このように入っているので、 f:id:matsujirushix:20170730221311p:plain

C:\TinyCLR\TinyCLR-Ports\CMSIS に配置します。 f:id:matsujirushix:20170730221752p:plain

TinyCLR Coreライブラリを配置

TinyCLR-PortsreleasesからTinyCLR_Core.0.5.0.zipをダウンロード、中身をTinyCLRのCore配下に配置します。

f:id:matsujirushix:20170730222158p:plain

よっしゃ、ビルドするぞー

コマンドプロンプトを立ち上げて、gcc環境変数設定バッチファイルを起動します。

"C:\Program Files (x86)\GNU Tools ARM Embedded\6 2017-q2-update\bin\gccvar.bat"

f:id:matsujirushix:20170730222418p:plain

次に、カレントディレクトリをクローンしたところに変更。

cd C:\TinyCLR\TinyCLR-Ports

そして、ビルドのバッチファイルを起動!

build.bat FEZ

f:id:matsujirushix:20170730222854p:plain

引数はFEZ, G30, G80, FEZCerberus, Netduino3, Quailが指定できます。 詳しくはbuild.batの中身を見てください。

おおーー!!

f:id:matsujirushix:20170730223030p:plain

最後に

NETMFと比べて、非常に簡単。特にハマるところは無いでしょう。

それにしてもビルドが速い。Coreの部分が事前にビルドされているから当たり前といえばそうですけど。

LLILUMの何時間もビルドした結果、エラーとか体感していると幸福感ありますw

TinyCLR OS デジタル出力

TinyCLR OSでデジタル出力を試しました。

環境は下記で作ったものを使用します。

matsujirushi.hatenablog.jp

デジタル出力のやり方は、General Purpose Input Output (GPIO)に丁寧に書かれています。素晴らしい。

パッケージソースに追加

デジタル出力するには、プロジェクトにGHIElectronics.TinyCLR.Devices.Gpioのnugetパッケージをインストールする必要があります。

しかし、TinyCLR OSがアルファ版のためか、まだnuget.orgにはアップされていません。

f:id:matsujirushix:20170726212624p:plain

そのため、適当なフォルダに.nupkgを置いて、パッケージソースにそのフォルダを追加することで、インストール可能にします。

ここからダウンロードできる、TinyCLR_Libraries.0.5.0.zipを適当なフォルダに解凍して、Visual Studioのパッケージソースに追加します。

f:id:matsujirushix:20170726213030p:plain

ライブラリをインストー

そして、プロジェクトにGHIElectronics.TinyCLR.Devicesをインストールします。

f:id:matsujirushix:20170726213434p:plain

Windows IoT Coreでお馴染みの、GpioControllerやGpioPinが含まれていますね。

f:id:matsujirushix:20170726213635p:plain

コーディング

プログラムはこんな感じ。

using GHIElectronics.TinyCLR.Devices.Gpio;
using System;
using System.Threading;

namespace TinyCLRApplication1
{
    class Program
    {
        static int PinNumber(char port, byte pin)
        {
            if (port < 'A' || port > 'E') throw new ArgumentException();
            return ((port - 'A') * 16) + pin;
        }

        static void Main()
        {
            for (;;)
            {
                GpioPin led = GpioController.GetDefault().OpenPin(PinNumber('D', 15));
                led.SetDriveMode(GpioPinDriveMode.Output);

                while (true)
                {
                    led.Write(GpioPinValue.High);
                    Thread.Sleep(100);
                    led.Write(GpioPinValue.Low);
                    Thread.Sleep(100);
                }
            }
        }
    }
}

実行

青色LEDが点滅すれば成功です。

f:id:matsujirushix:20170727224540p:plain

TinyCLR OS 環境構築方法

.NET MicroFrameworkが実質開発ストップしていますが、GHI Electronicsが分岐してシンプルにして(?)TinyCLR OSとして整備しているようです。

まだアルファ版ではありますが、現在公開されているTinyCLR OSの環境構築が上手くできたので、手順を書き留めておきます。

TinyCLRは未だアルファ版なので、リンクが切れたり手順が変更になったりする可能性があります。ご了承ください。

わたしの環境

作業前の、わたしのパソコン環境は次のとおりです。

使用するデバイスはSTM32F4 Discoveryです。

  • STM32F4 Discovery(STM32F407)

また、STM32F4 Discoveryに書き込むときに使用するdfu-utilは既にセットアップされていました。

必要なファイルをダウンロード

必要なファイルは次の3つです。

VisualStudio拡張

GHIElectronics.TinyCLR.VisualStudio.0.5.0.vsixです。

Tiny CLR Release Notesの0.5.0 on 2017-07-07をクリックした先のページでここからダウンロードできます。

ファームウェア

TinyCLR_Firmware.0.5.0.zipです。

Tiny CLR Release Notesの0.5.0 on 2017-07-07をクリックした先のページでここからダウンロードできます。

Windowsデバイスドライバ

GHI_TinyCLR_Interface.zipです。

フォーラムの回答からダウンロードできます。

VisualStudio拡張をインストー

GHIElectronics.TinyCLR.VisualStudio.0.5.0.vsixをダブルクリックで起動します。あとは画面の指示に従えばOKです。

f:id:matsujirushix:20170722211953p:plain

Visual Studio 2015も入っていたのに、Visual Studio 2017しか表示されていないので、どうやらVisual Studio 2017にしか対応していないようです。

f:id:matsujirushix:20170722212012p:plain

インストール完了後、Visual Studio拡張機能と更新プログラムで確認すると、TinyCLR OS Project Systemが追加されたことがわかります。

f:id:matsujirushix:20170722212159p:plain

プロジェクトの新規作成画面には、TinyCLRが追加されています。

f:id:matsujirushix:20170722212304p:plain

バイスとの接続方法はUSB/Serial/TCPIP。このあたりはNETMFのままですね。

f:id:matsujirushix:20170722212616p:plain

ファームウェアをデバイスにインストー

ここのやり方が分からず苦労しました。

STM32F4 Discoveryは、TinyCLR_Firmware.0.5.0.zipに含まれている、GHI Bootloader(FEZ Bootloader.2.0.3.dfu)をdfu-utilなどでフラッシュメモリに書き込み、そしてTeraTermなどでGHI Bootloaderに接続してファームウェアFEZ Firmware.0.5.0.glb)を転送します。

GHI Bootloaderの書き込み

STM32F4 DiscoveryをDFUモードで立ち上げます。下図のように、ボードの裏にあるJP2のジャンパーピンを外して、BOOT0とVDDを短絡します。

f:id:matsujirushix:20170723213030p:plain

そして、パソコンとUSB接続します。

ここはちょっとコツが必要で、STM32 DiscoveryのminiUSB(CN1)とmicroUSB(CN5)をUSB-HUBに接続しておき、USB-HUBをパソコンに接続して、両方のUSBを同時に接続しないといけないようです。(都市伝説なのかも?)

バイスマネージャにSTM32 BOOTLOADERが表示されれば成功です。

f:id:matsujirushix:20170723214345p:plain

そして、dfu-utilなどを使って、FEZ Bootloader.2.0.3.dfuフラッシュメモリに書き込んでください。

C:\>dfu-util -l
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Found DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path="1-1.4", alt=3, name="@Device Feature/0xFFFF0000/01*004 e", serial="3259375D3036"
Found DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path="1-1.4", alt=2, name="@OTP Memory /0x1FFF7800/01*512 e,01*016 e", serial="3259375D3036"
Found DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path="1-1.4", alt=1, name="@Option Bytes  /0x1FFFC000/01*016 e", serial="3259375D3036"
Found DFU: [0483:df11] ver=2200, devnum=7, cfg=1, intf=0, path="1-1.4", alt=0, name="@Internal Flash  /0x08000000/04*016Kg,01*064Kg,07*128Kg", serial="3259375D3036"

C:\>dfu-util -a 0 -D "FEZ Bootloader.2.0.3.dfu"
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Match vendor ID from file: 0483
Match product ID from file: 0000
Opening DFU capable USB device...
ID 0483:df11
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuERROR, status = 10
dfuERROR, clearing status
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash  "
file contains 1 DFU images
parsing DFU image 1
image for alternate setting 0, (1 elements, total size = 14744)
parsing element 1, address = 0x08000000, size = 14736
Download        [=========================] 100%        14736 bytes
Download done.
done parsing DfuSe file

C:\>

書き込みが完了したら、パソコンからUSB-HUBを外してJP2のジャンパーピンを元に戻します。

ファームウェアの書き込み

再び、USB-HUBをパソコンに接続すると、COMが2つ表示されるので、下の方にTeraTermで接続します。

f:id:matsujirushix:20170726210754p:plain

COMが1つしか表示されないときは、GHI Bootloaderがすでにフラッシュメモリに存在するプログラムを起動しています。 このような場合は、PA15をGNDに繋ぎながらパソコンに接続すると、プログラム起動を抑止してCOMが2つ表示されます。

TeraTermで接続したGHI Bootloaderで、Uを入力してからFEZ Firmware.0.5.0.glbをXMODEMで送信します。送信のときに、オプションの1Kにチェックを付けてください。

HI Electronics, LLC Bootloader
-------------------------------
OK.
Are you sure (Y/N)?
Waiting...
CCCCCCCCCCCCCCCCCCCCCCCCCCCCC
OK.

f:id:matsujirushix:20170726211126p:plain

再び、USB-HUBを外して、USB-HUBをパソコンに接続すると、FEZという不明なデバイスが表示されればOKです。

f:id:matsujirushix:20170723222107p:plain

Windowsデバイスドライバをインストー

GHI_TinyCLR_Interface.zipを適当なフォルダに解凍しておき、さきほどのFEZという不明なデバイスどのドライバ更新でzip解凍先を指定します。

f:id:matsujirushix:20170723222334p:plain

f:id:matsujirushix:20170723222350p:plain

FEZのビックリマークが消えればOKです。

f:id:matsujirushix:20170723222538p:plain

Visual Studioから認識できるか確認

適当にTinyCLRプロジェクトを新規作成して、プロジェクトのプロパティにあるDeviceにFEZ_FEZと表示されれば、デバイスがきちんと認識できています。

f:id:matsujirushix:20170723222738p:plain

最後に

とりあえずデバイスをセットアップすることができました。

次は、GPIOのやり方を確認したいと思います。