「Azure IoT Edge で Custom Vision」のハンズオン資料を公開しました

Azure IoT Edge + Custom Visionでエッジデバイスで画像分類 するソリューション作成のハンズオン資料を公開しました。

https://github.com/seosoft/IoTCvCatsDogs

先日の勝手に勉強会で話した内容 を、実際に自分で実行することができます。

細かい手順まで書いているので、Custom Vision をよく知らない、Azure IoT をよく知らない人でも最後までたどり着けるはず。
ぜひお試しください。

それにしても、Custom Vision の強力なこと。
深層学習の知識がなくても、簡単に 画像分類 するソリューションを作成できます。
しかもエッジデバイスで動作するなんて。

セッション資料「Azure IoT Edge で Custom Vision」 ( #勝手に勉強会 2020年4月19日開催) を公開しました

@kenakamu108 さんがやっている 勝手に勉強会 に、勝手に乱入してお話しさせていただきました。

Custom Vision の学習済みのモデルを IoT Edge デバイス 上で動作させる手順の紹介です。

デモアプリのソースコードは GitHub (https://github.com/seosoft/IoTCvCatsDogs) に上げました。
未整理ですが、参考になれば。
(もしかしたら説明を追加してハンズオン資料化するかも・・・もしかしたら)

続きを読む

#SORACOM LTE-M Button の簡易位置情報を SORACOM #Funk を通して Azure Functions (C#) で取得する

LTE-M button の簡易位置情報を Azure Functions (C#) で取得する」シリーズの第3弾、完結編です。(そんな大袈裟なものなのか)

今回は Azure Functions にデプロイした C# なアプリケーションで、ボタンの位置情報SORACOM Funk 経由で取得します。

位置情報取得シリーズはこんな構成。

続きを読む

#SORACOM LTE-M Button の簡易位置情報を Azure Functions (C#) で取得する

前の投稿で「LTE-M button の簡易位置情報をローカル PC で実行している C# アプリで取得」しました。

今回はそれの続き、Azure Functions にデプロイ してみます。SORACOM Beam ならローカルで動作確認したものを単にデプロイするだけです。
わざわざ分けて投稿するまでもないんですが、前回は途中で終わってしまった感があるので、今回は真面目に「クラウド連携」します。

今回は素直に Beam 経由です。

「Azure Functions、何それ?おいしいの?」という人もいるかもしれないので、動作確認、というかログの出し方についてもチラッと書きます。
(知っている人には当たり前すぎる内容ですが)

続きを読む

#SORACOM LTE-M Button の簡易位置情報をローカルPC上のC#アプリで取得してみる

SORACOM LTE-M Button で簡易位置情報を取得できるようになりました。

https://blog.soracom.jp/blog/2019/08/01/location-function-release/

「それでは」ということで早速試してみます。

今回、位置情報を確認するための手順は以下の通り。

  • SORACOM ユーザーコンソールでの設定
  • SORACOM Harvest でデータの確認
  • Azure Functions のプロジェクトをローカルで作成
  • ngrok で localhost を公開
  • SORACOM Beam の設定
  • 動作確認

ローカルで Azure Functions を開発する環境としては、今回は Visual Studio Code を使います。

続きを読む

大迫力の ゴジラ・ナイト を体験してきました (+ ほんのちょっとだけ技術の考察) #hibiya2018 #godzilla

開催中の「ゴジラ・ナイト」を体験してきました。

gozillanights_logo

5月24日 (木) から 29日 (火) までの開催で、すでに抽選は終わっています。これを読んで「面白そう、行ってみたい!」と思った方がいたら、ごめんなさい。

この辺りのレポート でライターさんも大興奮で書いているので、雰囲気は伝わるかな。

続きを読む

【2017年版】Visual Studio で Arduino 開発

Arduino と言えば、普通は開発には Arduino IDE を使うと思いますが、ここでは Visual Studio で Arduino 開発ができますよ、しかもより効率的に開発できますよというお話。

2~3年ごとに、Visual Studio での Arduino 開発の記事を書いています。本当にたまたまなんですが、今回が3回目。
やんごとなき理由 で久しぶりに Arduino を触っておこうと思い、せっかくなのでデバッグあたりも見てみました(と言っても、作ったスケッチは L チカなんですが・・・)。

Visual Studio を使っちゃうと、申し訳ないですが Arduino IDE には戻れないですね。

続きを読む

Windows 10 IoT をアプリでデバイスシャットダウンする方法

今回は、Windows 10 IoT でアプリからデバイスをシャットダウン(再起動)する方法。

他のマイコンボードだと、いきなり給電を止めても問題ありません。
microSD に書き込み中に電源を落としたりすると、カードの中身を破損する可能性はあると思うので絶対安全とは言えませんが、それほど神経質になることもないと思います。

それに対して、Windows 10 IoT はやむを得ない場合を除いて、ちゃんとシャットダウンしてあげるべきです。Windows です。“OS”です。
それなのにディスプレイもマウス・キーボードも接続していないということもあるでしょう。

そこでアプリでデバイスをシャットダウンしたくなります。タクトスイッチを押すとか、IoT Hub からメッセージを送るとかのタイミングでシャットダウンプロセスを起動することが考えられます。


Windows 10 IoT を楽しんでいる人ならば馴染みのある画面。

2017-01-26 23-08-27

ご承知のように、Windows 10 IoT はデフォルトシェルを持っていません。見慣れた画面も “IoT Core Default App” なるごく普通の UWP アプリケーション。
ソースコード が公開されているので、シャットダウンの方法もすぐにわかるでしょう

実際に、ソースコードを展開して、”Shutdown” を検索すればすぐに見つかります。
MainPage.xaml.csShutdownManager クラスの BeginShutdown  を呼び出しています。なるほど。

真似をしてこんなコードを書いてみました。起動して10秒後に自動的にシャットダウンしてしまうという、無意味この上ないアプリケーション(笑)。

using System;
using System.Threading.Tasks;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace ShutdownDemo01
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void MainPage_OnLoaded(object sender, RoutedEventArgs e)
        {
            Task.Delay(TimeSpan.FromSeconds(10)).Wait();

            new System.Threading.Tasks.Task(() =>
            {
                ShutdownManager.BeginShutdown(ShutdownKind.Shutdown, TimeSpan.FromSeconds(0));
            }).Start();
        }
    }
}

 

実行してみるとこんなことになりました・・・。

2017-01-25 23-59-44

・・・“UnauthorizatedAccessException”。
さすが UWP アプリケーション、デバイスの機能を利用するには機能の指定が必要なようです。

残念ながら、ソリューションエクスプローラーの Package.appxmanifest をダブルクリックして開いても該当しそうな機能がリストに見つかりません。

2017-01-26 23-29-34

仕方ないのでここで改めて、先ほどダウンロードした IoT Core Default App のソースコードを参考にしてみます。

Package.appxmanifest を右クリックして、コードの表示を選択します。

2017-01-26 0-00-58

変更箇所は2か所。

Package 要素に属性を一つ追加。もう一つは一番下の Capabilities に要素を一つ追加。こうなります。

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
  IgnorableNamespaces="uap mp iot">

  <Identity
    Name="c626b4f7-7b52-4c90-90cb-9606fdce05c8"
    Publisher="CN=taka"
    Version="1.0.0.0" />

  <mp:PhoneIdentity PhoneProductId="c626b4f7-7b52-4c90-90cb-9606fdce05c8" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

  <Properties>
    <DisplayName>ShutdownDemo01</DisplayName>
    <PublisherDisplayName>taka</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>

  <Resources>
    <Resource Language="x-generate"/>
  </Resources>

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="ShutdownDemo01.App">
      <uap:VisualElements
        DisplayName="ShutdownDemo01"
        Square150x150Logo="Assets\Square150x150Logo.png"
        Square44x44Logo="Assets\Square44x44Logo.png"
        Description="ShutdownDemo01"
        BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
    </Application>
  </Applications>

  <Capabilities>
    <Capability Name="internetClient" />
    <iot:Capability Name="systemManagement" />
  </Capabilities>
</Package>

 

以上で、無事にアプリからシャットダウンできるようになりました。めでたしめでたし。

IoT Hub 経由でデバイスにメッセージを送信する

IoT Hub にはデバイスにメッセージを送信する機能がありますが、前の記事では送信元として Device Explorer を使用しました。API が用意されているので、任意のアプリケーションから IoT Hub を経由してメッセージを送信することができます。今回はそのお話。

IoT Hub とデバイス(主に Windows 10 IoT)との通信や管理についての記事をいくつか投稿しました。本稿と合わせてご覧ください(以下の記事を順に読んで、最後に本稿を読むことをお勧めします)。


■ メッセージの送信の仕方

アプリケーションから IoT Hub 経由でデバイスにメッセージを送信するには、ServiceClient クラスの SendAsync メソッドを使います。

ServiceClient _client = ServiceClient.CreateFromConnectionString(ConnectionString);
await _client.SendAsync([デバイスID], [Message]);

こんな感じです。

Message は

var message = new Message(Encoding.ASCII.GetBytes(DeviceMessageBox.Text));

こんな感じでバイト配列にしておけば OK。

デバイスから IoT Hub にメッセージを送るのにそっくりです。
違いは、デバイスから IoT Hub に送る場合は DeviceClient クラスを使い、IoT Hub からデバイスにメッセージを送るには ServiceClient クラスを使うこと。
どちらも Client クラスのインスタンス生成は CreateFromConnectionString スタティックメソッドを使うのは同じです。


■ サンプルコード

サンプルコードのベースは こちらの記事 ですが、MainWindow.xaml および MainWindow.xaml.cs を以下のように変更してみました。デバイスにメッセージを送信するのは SendMessageButton_Click メソッドの部分です。

DeviceMaiager.cs は今回の内容には関係ないので、前の記事のままで持ってくればビルドに成功するはず。
もちろん送信元のアプリが WPF である必要はありません。

<Window x:Class="IoTDeviceManager.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:IoTDeviceManager"         mc:Ignorable="d"         Title="IoT Hub Device Manager" Height="350" Width="525">
    <Grid>
        <Label x:Name="DeviceIdLabel" Content="デバイスID" HorizontalAlignment="Left" Margin="31,28,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="DeviceIdBox" HorizontalAlignment="Left" Height="23" Margin="115,31,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360"/>
        <Label x:Name="PrimaryKeyLabel" Content="プライマリキー" HorizontalAlignment="Left" Margin="31,81,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="PrimaryKeyBox" HorizontalAlignment="Left" Height="23" Margin="115,81,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360" IsReadOnly="True"/>
        <Label x:Name="StateLabel" Content="状態" HorizontalAlignment="Left" Margin="31,131,0,0" VerticalAlignment="Top"/>
        <RadioButton x:Name="EnabledButton" Content="有効" HorizontalAlignment="Left" Margin="115,137,0,0" VerticalAlignment="Top" GroupName="StateGroup" IsChecked="True"/>
        <RadioButton x:Name="DisabledButton" Content="無効" HorizontalAlignment="Left" Margin="190,137,0,0" VerticalAlignment="Top" GroupName="StateGroup"/>
        <Label x:Name="DeviceMesageLabel" Content="メッセージ" HorizontalAlignment="Left" Margin="31,183,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="DeviceMessageBox" HorizontalAlignment="Left" Height="23" Margin="115,186,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="360"/>
        <Button x:Name="CreateButton" Content="登録" HorizontalAlignment="Left" Margin="31,260,0,0" VerticalAlignment="Top" Width="75" Click="CreateButton_Click"/>
        <Button x:Name="GetButton" Content="取得" HorizontalAlignment="Left" Margin="111,260,0,0" VerticalAlignment="Top" Width="75" Click="GetButton_Click"/>
        <Button x:Name="SetStateButton" Content="状態変更" HorizontalAlignment="Left" Margin="191,260,0,0" VerticalAlignment="Top" Width="75" Click="SetStateButton_Click"/>
        <Button x:Name="SendMessageButton" Content="送信" HorizontalAlignment="Left" Margin="271,260,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.353,0.629" Click="SendMessageButton_Click"/>
        <Button x:Name="DeleteButton" Content="削除" HorizontalAlignment="Left" Margin="400,260,0,0" VerticalAlignment="Top" Width="75" Click="DeleteButton_Click"/>
    </Grid>
</Window>
using System.Text;
using System.Windows;
using Microsoft.Azure.Devices;

namespace IoTDeviceManager
{
    public partial class MainWindow : Window
    {
        private const string ConnectionString = "HostName=[ホスト名].azure-devices.net;SharedAccessKeyName=[アクセスキー名];SharedAccessKey=[アクセスキー]";

        private readonly DeviceManager _manager;
        private readonly ServiceClient _client;

        public MainWindow()
        {
            InitializeComponent();

            _manager = new DeviceManager(ConnectionString);
            _client = ServiceClient.CreateFromConnectionString(ConnectionString);
        }

        private async void CreateButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.CreateDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void GetButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.GetDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void SetStateButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            var device = await _manager.GetDevice(DeviceIdBox.Text);
            if (device == null)
                return;

            device.Status =
                EnabledButton.IsChecked.HasValue && EnabledButton.IsChecked.Value ?
                DeviceStatus.Enabled : DeviceStatus.Disabled;

            device = await _manager.SetDeviceStatus(device);
            if (device == null)
                return;

            PrimaryKeyBox.Text = device.Authentication.SymmetricKey.PrimaryKey;
            if (device.Status == DeviceStatus.Enabled)
                EnabledButton.IsChecked = true;
            else
                DisabledButton.IsChecked = true;
        }

        private async void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            PrimaryKeyBox.Text = string.Empty;
            if (string.IsNullOrEmpty(DeviceIdBox.Text))
                return;

            await _manager.DeleteDevice(DeviceIdBox.Text);
        }

        // アプリから Iot Hub 経由でデバイスにメッセージを送信する
        private async void SendMessageButton_Click(object sender, RoutedEventArgs e)
        {
            var message = new Message(Encoding.ASCII.GetBytes(DeviceMessageBox.Text));
            await _client.SendAsync(DeviceIdBox.Text, message);
        }
    }
}

 

本稿を含めて 4会の記事で、IoT Hub とデバイスとの通信についての説明は終わり。
IoT Hub を使って面白いシステムをどんどん作ってみてください。