MRが楽しい

MRやVRについて学習したことを書き残す

Blenderで視点の中心位置をオブジェクトまたはワールド原点に合わせる

本日は Blender の小ネタ枠です。
Blenderで視点の回転の中心位置をオブジェクトまたはワールド原点に合わせる手順を記事にします。
f:id:bluebirdofoz:20210702232303j:plain

視点の中心位置

Blender では視点の中心位置をマウスホイール押し込みとドラッグ操作で移動することができます。
f:id:bluebirdofoz:20210702232312j:plain

視点の中心位置をオブジェクトに合わせる

操作している内に視点の中心が分からなくなった場合は、[3Dビューポート]の[ビュー -> 視点を揃える -> アクティブに注視]で視点の中心を選択中のオブジェクト位置に戻すことができます。
f:id:bluebirdofoz:20210702232322j:plain

以下の通り、オブジェクトが注視点となり、視点の中心が選択中のオブジェクト位置になりました。
f:id:bluebirdofoz:20210702232331j:plain

注視状態は[ビュー -> 視点を揃える -> ビューの注視のクリア]から解除できます。
f:id:bluebirdofoz:20210702232340j:plain

視点の中心位置と3Dカーソルをワールド原点にリセットする

[Shift + C]または[ビュー -> 視点を揃える -> 3Dカーソルのリセットと全表示]を実行すると、視点の中心位置と3Dカーソルをワールド原点にリセットすることもできます。
f:id:bluebirdofoz:20210702232353j:plain

視点を色々と動かす際はこのショートカットキーを覚えておくと、便利です。
f:id:bluebirdofoz:20210702232403j:plain

MRTK 2.7 のインポートと HoloLens2 向け基本設定の手順

本日は MRTK の使い方枠です。
MRTK 2.7 のインポートと HoloLens2 向け基本設定の手順を記事にします。
f:id:bluebirdofoz:20210701023234j:plain

MRTKとは

MRTK-Unity は Unity でのクロスプラットフォームのMRアプリ開発を支援するための機能セットを提供する Microsoft 主導のプロジェクトです。

・空間的な相互作用と UI に対するクロスプラットフォーム入力システムと構成要素を提供します。
・エディタ内シミュレーションを介したプロトタイピングを可能にし、プロジェクトの変更をすぐに確認できます。
・開発者がコアコンポーネントを交換できるようにする拡張可能なフレームワークとして設計されています。
・幅広いプラットフォームのサポートを含みます。

プラットフォームサポートデバイス
OpenXR (Unity 2020.3)Microsoft HoloLens 2
Windows Mixed Reality ヘッドセット
Windows Mixed RealityMicrosoft HoloLens
Microsoft HoloLens 2
Windows Mixed Reality ヘッドセット
Oculus (Unity 2019.3 or newer)Oculus Quest
OpenVRWindows Mixed Reality ヘッドセット
HTC Vive
Oculus Rift
Ultraleap Hand TrackingUltraleap Leap Motion controller
MobileiOS
Android

github.com

MRTKのダウンロード

MRTK には以下の3つの取得方法があります。
・Unity Package
・Unity Package Manager
・Mixed Reality Feature Tool

今回は Release ページから Unity Package ファイルを直接取得する手順を紹介します。
github.com
f:id:bluebirdofoz:20210701023258j:plain

MRTK のパッケージリンクをクリックしてダウンロードします。
2021/07/01 現在、最新のバージョンは v 2.7.2 です。
f:id:bluebirdofoz:20210701023346j:plain

各パッケージについて

MRTK には以下の5つのパッケージが存在します。
・Foundation:基本パッケージ
・Examples:MRTKの利用サンプルシーンを含むパッケージ
・Tools:便利なツール機能を含むパッケージ
・Extensions:試験中の拡張機能を含むパッケージ
・TestUtilities:テスト用機能を含むパッケージ

必須となるのは Foundation のみです。
その他のパッケージは全てオプションとなります。

プロジェクトの新規作成

Unityプロジェクトの作成

v2.7.2 における MRTK の推奨 Unity バージョンは 2019.4 になります。
Unity を起動して[新しいプロジェクトの作成]を行います。
f:id:bluebirdofoz:20210701023402j:plain

ビルドターゲットの変更

HoloLens2 向けのアプリケーションを作成する場合はビルドプラットフォームを UWP に変更します。
メニューから[File -> Build Settings]を選択し、[Build Settings]ダイアログを開きます。
f:id:bluebirdofoz:20210701023416j:plain

[Platform]で[Universal Windows Platform]を選択し、[Switch Platform]を実行します。
f:id:bluebirdofoz:20210701023428j:plain

パッケージのインポート

利用する Unity Package のインポートを行います。
今回は Microsoft.MixedReality.Toolkit.Unity.Foundation のみインポートします。
f:id:bluebirdofoz:20210701023439j:plain

Foundation パッケージはインポート完了時に[MRTK Project Configurator]ダイアログが表示されます。
表示されない、または閉じてしまった場合は[Mixed Reality -> Toolkit -> Utilities - Configure Project for MRTK]から開くことができます。
f:id:bluebirdofoz:20210701023452j:plain

なお、オプションパッケージを利用する場合も必ず Foundation からインポートを行います。

プロジェクトの基本設定

最初に XR パイプラインに[Legacy XR]または[XR SDK]のどちらを利用するか選択します。
今回は最新の[XR SDK]を選択します。
f:id:bluebirdofoz:20210701023504j:plain

ターゲットデバイス向けのプラグインの要求ダイアログが表示されます。
[Show Settings]をクリックして[Project Settings]ダイアログを開きます。
f:id:bluebirdofoz:20210701023519j:plain

HoloLens2 向けのアプリケーションを作成する場合は[UWP]タブを開きます。
[Plug-in Providers]内の[Windows Mixed Reality]にチェックを入れます。
f:id:bluebirdofoz:20210701023530j:plain

目的のビルドターゲットの XR プラグインを指定しているかの確認ダイアログが表示されます。
HoloLens 向けのアプリケーション作成であれば、先ほどの手順通りのチェックをしていれば問題ありません。
f:id:bluebirdofoz:20210701023541j:plain

プロジェクトの基本設定ダイアログが表示されるので[Apply]をクリックします。
ここでは以下の設定が行われます。
・デフォルトの空間認識レイヤーを作成する
・マイクの権限設定を許可にする
f:id:bluebirdofoz:20210701023554j:plain

設定が完了すると、確認ダイアログに切り替わるので[Next]をクリックします。
f:id:bluebirdofoz:20210701023608j:plain

TextMeshPro のインポートダイアログが表示されます。
MRTK では多くの UI に TextMeshPro が利用されているので、ここで[Import TMP Essentials]をクリックしてインポートを行います。
f:id:bluebirdofoz:20210701023624j:plain

これでプロジェクトの基本設定は完了です。
f:id:bluebirdofoz:20210701023635j:plain

シーンの基本構成

次に HoloLens2 向けのアプリケーションのシーンの基本構成を設定します。
メニューから[Mixed Reality -> Toolkit -> Add to Scene and Configure..]を選択します。
f:id:bluebirdofoz:20210701023646j:plain

するとシーンの Hierarchy に以下のゲームオブジェクトが追加されます。
・MixedRealityToolkit
・MixedRealityPlayspace
・MixedRealitySceneContent

Mixed Reality Toolkit:フレームワーク全体の中央構成エントリポイントを提供するツールキットの本体。
MixedRealityPlayspace:ヘッドセットの親オブジェクト。ヘッドセット/コントローラーおよびその他の必要なシステムを管理します。メインカメラはプレイスペースの子オブジェクトとして移動します。
MixedRealitySceneContent:デバイスごとに適切にスケーリングするシーンコンテンツの配置場所。

f:id:bluebirdofoz:20210701023701j:plain

次に HoloLens2 に最適化されたシーン設定とするため、プロファイルを設定します。
MixedRealityToolkit オブジェクトを選択し、Inspector ビューを開きます。
f:id:bluebirdofoz:20210701023715j:plain

プルダウンからいくつかのデフォルト設定のプロファイルを選択できます。
XR パイプラインに[XR SDK]を選択しており、かつ、HoloLens2 に最適化されたシーン設定とする場合[ObsoleteHololens2XRSDKConfigurationProfile]を選択します。
f:id:bluebirdofoz:20210701023726j:plain

[ObsoleteHololens2XRSDKConfigurationProfile]は HoloLens2 向けに最適化されたプロファイルです。
負荷軽減のため、空間メッシュやハンドメッシュが無効化されています。
f:id:bluebirdofoz:20210701023743j:plain

パッケージ名の変更(オプション)

メニューから[Edit -> Project Settings]を開き、[Player -> UWP -> Publishing Settings]の項目を開きます。
[Package name]の項目をデフォルトの[Template3D]から任意のパッケージ名に変更します。
f:id:bluebirdofoz:20210701023754j:plain

パッケージ名の変更はアプリの作成において必須の作業ではありません。
しかし、同名のパッケージ名のアプリが存在するとインストール時にアプリを上書きするなどの問題が発生するので変更することを推奨します。
f:id:bluebirdofoz:20210701023804j:plain

これでMRTK 2.7 のインポートと HoloLens2 向け基本設定は完了です。

AzureのSignalRServiceを使ってサーバからHoloLens2にデータを送信する記事をまとめる

本日はまとめ記事です。
「AzureのSignalRServiceを使ってサーバからHoloLens2にデータを送信する」の記事をまとめます。

参考記事

これらの記事は以下の記事を参考に、実施した作業記録です。
blog.xin9le.net

実施記録

作業の実施記録は以下の通りです。

Azure リソースの作成

bluebirdofoz.hatenablog.com

Azure Functionの関数作成

bluebirdofoz.hatenablog.com

クライアントアプリの作成

bluebirdofoz.hatenablog.com

Authorization levelをFunctionにした場合

bluebirdofoz.hatenablog.com

HoloLens2 用クライアントアプリの作成

bluebirdofoz.hatenablog.com

その他の参照記事

Azure SignalR Service の Service Mode 設定による違い

blog.shibayan.jp

Unity で ASP.NET Core SignalR を利用する

blog.xin9le.net

AzureのSignalRServiceを使ってサーバからHoloLens2にデータを送信する その5(HoloLens2 用クライアントアプリの作成)

本日は Azure と HoloLens2 の技術調査枠です。
Azure の SignalRService を使ってサーバから HoloLens2 にデータを送信する方法を試したので作業記録を記事にします。
f:id:bluebirdofoz:20210629025910j:plain

前回記事の続きです。
bluebirdofoz.hatenablog.com

HoloLens2用クライアントアプリの作成

SignalR Service からデータを受信する HoloLens2 用クライアントアプリを作成します。

プロジェクトの作成

最初に以下の記事などを参考に、MRTK を用いて HoloLens2 用の基本シーンを構成します。
bluebirdofoz.hatenablog.com
f:id:bluebirdofoz:20210629025939j:plain

今回は XR パイプラインに XRSDK を利用しています。
f:id:bluebirdofoz:20210629025949j:plain

依存パッケージのインポート

Microsoft.AspNetCore.SignalR.Client の参照を解決するため、NuGetForUnity を利用して依存パッケージをインポートします。
NuGetForUnity の使い方は以下の記事などを参考にしてください。
bluebirdofoz.hatenablog.com
f:id:bluebirdofoz:20210629030005j:plain

Microsoft.AspNetCore.SignalR.Client を検索して[Install]を実行します。
f:id:bluebirdofoz:20210629030015j:plain

参照エラーの解消

筆者環境ではパッケージをインポートすると、参照ライブラリのバージョンが異なることを示す以下のエラーメッセージが発生しました。

Assembly references: X.X.X.X Found in project: Y.Y.Y.Y.
Assembly Version Validation can be disabled in Player Settings "Assembly Version Validation".

f:id:bluebirdofoz:20210629030305j:plain

UWP プラットフォームを指定している場合、"Assembly Version Validation"の設定を無効化することはできません。
f:id:bluebirdofoz:20210629030315j:plain

このエラーメッセージは全ての DLL を同じ階層のディレクトリに配置することで解消できるので、今回はこの方法でエラーを解消しました。
f:id:bluebirdofoz:20210629030336j:plain

バイトコードストリップの対処

また、本プロジェクトをこのままビルドした場合、バイトコードストリップの機能によって Microsoft.AspNetCore.SignalR 内の型が展開されない問題が発生します。
この問題が発生すると、ビルドは正常に通るものの HoloLens2 上では特定の型が利用できないエラーが発生して SignalR の接続が行えません。

System.InvalidOperationException:
A suitable constructor for type 'Mycrosoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory' could not be located.
Ensure the type is concrete and services are registered for all parametaers of a public constructor.

f:id:bluebirdofoz:20210629030512j:plain

この問題は Assets フォルダ内に link.xml ファイルを作成し、指定の型へのバイトコードストリップを無効化することで解消できます。
docs.unity3d.com

今回は以下の link.xml ファイルを作成し、DLL のフォルダに配置しました。
・link.xml

<linker>
  <assembly fullname="Microsoft.AspNetCore.Connections.Abstractions" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.Http.Features" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.SignalR.Common" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.SignalR.Protocol.MessagePackHubProtocol" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.DependencyInjection.Abstractions" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.Options" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.Primitives" preserve="all"/>
  <assembly fullname="Microsoft.Bcl.AsyncInterfaces" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.Http.Connections.Client" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.Http.Connections.Common" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.SignalR.Client.Core" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.SignalR.Client" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.SignalR.Protocols.Json" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.Configuration.Abstractions" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.Configuration.Binder" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.Configuration" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.DependencyInjection" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.Logging.Abstractions" preserve="all"/>
  <assembly fullname="Microsoft.Extensions.Logging" preserve="all"/>
  <assembly fullname="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" preserve="all"/>
</linker>

f:id:bluebirdofoz:20210629030600j:plain

必要な型の抽出は以下の Digital Twin のプロジェクト内の link.xml を参考にしました。
bluebirdofoz.hatenablog.com

Microsoft.AspNetCore.SignalR でバイトコードストリップの問題が発生する理由については以下の記事が詳しいです。
blog.xin9le.net

以下、上記記事からの抜粋です。

IL2CPP ビルドには バイトコードストリップ という大きな特徴があります。
要は静的構文解析の結果として利用されていない型は C++ コードとして展開されないというものです。
・明示的に型を利用しない限り消える
・リフレクション経由でインスタンス化されているものは型を「利用していない」判定される
(中略)
ASP.NET Core SignalR でバイトコードストリップが発生するのかと言うと、ASP.NET Core の内部で DI (= Dependency Injection) が利用されているためです。
つまりリフレクション経由でインスタンス生成をしているからなのですが、これが IL2CPP と非常に相性が悪いです。

サンプルシーンの作成

必要なパッケージをインポートしたのでシーンを構成します。
SignalR Service に接続してデータを受信し、Text コンポーネントに結果を表示する以下のスクリプトを作成しました。
・HoloSideSignalRConnection.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

using System;
using System.Net.Http;
using Microsoft.AspNetCore.SignalR.Client;

public class HoloSideSignalRConnection : MonoBehaviour
{
    /// <summary>
    /// 表示UIテキスト 
    /// </summary>
    [SerializeField, Tooltip("表示UIテキスト")]
    private Text UIText;
    
    private const string RootUrl = "https://xxxxxxxxxxxxxxxxxxxx.azurewebsites.net";  // 作った Azure Functions の URL
    private const string FuctionKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  // 作った Azure Functions の関数 Key

    private HubConnection Connection;

    public string ShowTextMessage = "";
    private bool changeText = false;
    
    /// <summary>
    /// 起動時処理
    /// </summary>
    void Start()
    {
        try
        {
            // negotiate 関数の URL と headers 情報を設定する
            this.Connection = new HubConnectionBuilder().WithUrl($"{RootUrl}/api",
            options =>
            {
                options.Headers["x-functions-key"] = FuctionKey;
            }).Build();
            
            // Azure SignalR Service から Push されてきたメッセージを受信する
            Connection.On<string>("Receive", data =>
            {
            // 表示テキストとして保持する
            ShowTextMessage = data;
                changeText = true;
            });
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.ToString());
        }
    }

    /// <summary>
    /// 定期処理
    /// </summary>
    private void Update()
    {
        if (changeText)
        {
            // メインスレッドでテキストをシーンに反映する
            UIText.text = ShowTextMessage;
            changeText = false;
        }
    }

    /// <summary>
    /// 接続処理
    /// </summary>
    public async void OnConnectClick()
    {
        Debug.Log("OnConnectClick");
        try
        {
            await Connection.StartAsync();  // '/negotiate' から接続情報を取得して接続
            ShowTextMessage = "Connected!";
            changeText = true;
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.ToString());
        }
    }

    /// <summary>
    /// 切断処理
    /// </summary>
    public async void OnDisconnectClick()
    {
        Debug.Log("OnDisconnectClick");
        try
        {
            await Connection.StopAsync();  // 切断
            ShowTextMessage = "Disconnected!";
            changeText = true;
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.ToString());
        }
    }
}

f:id:bluebirdofoz:20210629030813j:plain

シーンに結果表示用の Text オブジェクトと、Connect/Disconnect 用のボタンを配置します。
f:id:bluebirdofoz:20210629030825j:plain

シーンにスクリプトを配置し、Text オブジェクトへの参照を設定します。
f:id:bluebirdofoz:20210629030838j:plain

2つのボタンにはそれぞれ接続/切断処理の関数を実行する OnClick イベントを設定しておきます。
f:id:bluebirdofoz:20210629030850j:plain

HoloLens2へのインストールと動作確認

以下の記事などを参考に、作成したアプリを HoloLens2 にインストールします。
bluebirdofoz.hatenablog.com

インストールが完了したら、HoloLens2 上でアプリを起動します。
初期状態では Text オブジェクトにデフォルトのテキストメッセージが表示されます。
f:id:bluebirdofoz:20210629030933j:plain

接続処理を実行するボタンをクリックすると SignalR Service への接続が行われ、成功すると[Connected!]の文字が表示されます。
もし、前述のバイトコードストリッピングの問題が正しく行われていない場合はここで接続に成功しません。
f:id:bluebirdofoz:20210629030945j:plain

接続に成功したら、SignalR Service からデータを送信してみます。
前回記事で作成した PC 側のクライアントアプリを起動し、SignalR Service に接続して[broadcast]を実行します。
f:id:bluebirdofoz:20210629031009j:plain

HoloLens2 側で SignalR Service を通し、送信された時刻情報の文字列を受信できれば成功です。
f:id:bluebirdofoz:20210629031022j:plain

AzureのSignalRServiceを使ってサーバからHoloLens2にデータを送信する その4(Authorization levelをFunctionにした場合)

本日は Azure と HoloLens2 の技術調査枠です。
Azure の SignalRService を使ってサーバから HoloLens2 にデータを送信する方法を試したので作業記録を記事にします。
f:id:bluebirdofoz:20210628225001j:plain

前回記事の続きです。
bluebirdofoz.hatenablog.com

Azure FunctionのAuthorization levelをFunctionにした場合

前回記事で Tips に記述した通り、Authorization level を Anonymous にした場合、URL を知っていれば誰でもアクセス可能になります。
本記事では Authorization level を Function に設定し、関数キーを知っている人のみアクセス可能なようにする場合の手順を記録します。

Azure Function関数の変更

最初に Azure Function に登録している関数の Authorization level を Function に変更します。

パッケージで作成済みの関数を削除する

前々回作成した関数を削除します。
ただしパッケージファイルから発行した関数は[関数]タブからは削除できません。
f:id:bluebirdofoz:20210628225138j:plain

パッケージファイルから発行した関数を削除するには[構成]タブを開きます。
[WEBSITE_RUN_FROM_PACKAGE]の設定を削除し、変更内容を[保存]します。
f:id:bluebirdofoz:20210628225152j:plain

これで作成した関数が削除されます。
f:id:bluebirdofoz:20210628225206j:plain

Authorization levelの変更

Azure Function の関数プロジェクトを開きます。
以下の通り、AuthorizationLevel の設定を AuthorizationLevel.Function に変更します。
f:id:bluebirdofoz:20210628225217j:plain

この設定で改めて関数の発行を行います。
f:id:bluebirdofoz:20210628225228j:plain

発行が完了したら設定が正しく行われているか AzurePortal で確認してみます。
Azure Function のページを開き、[関数]タブから関数を選択します。
f:id:bluebirdofoz:20210628225245j:plain

関数のページが開いたら[コードとテスト]タブを開きます。
[authLevel]の項目が[function]になっていれば、正しく設定できています。
f:id:bluebirdofoz:20210628225303j:plain

クライアントアプリの変更

次にクライアントアプリを修正します。

関数キーの取得

Authorization level が Function の関数にアクセスするには関数キーが必要です。
関数のページを開き、[関数キー]タブを開きます。
f:id:bluebirdofoz:20210628225316j:plain

関数キーの[値]を表示し、メモしておきます。
f:id:bluebirdofoz:20210628225325j:plain

なお、関数キーは関数ごとにメモしておく必要があります。
今回は negotiate と broadcast の2つの関数の関数キーをメモしました。
f:id:bluebirdofoz:20210628225338j:plain

x-functions-keyの追加

クライアントアプリのプロジェクトを開きます。
それぞれの関数アクセスに x-functions-key の headers 情報を追加します。
f:id:bluebirdofoz:20210628225459j:plain

HubConnectionBuilder().WithUrl 関数の場合は以下の通り、headers 情報を設定します。

this.Connection = new HubConnectionBuilder().WithUrl($"{RootUrl}/api",
    options =>
    {
        options.Headers["x-functions-key"] = AZURE_FUNCTION_KEY;
    }).Build();

HttpClient の場合は以下の通り、headers 情報を設定します。

this.HttpClient.DefaultRequestHeaders.Add("x-functions-key", AZURE_FUNCTION_KEY);

AZURE_FUNCTION_KEY の部分にはそれぞれの関数キーを設定します。
コードを以下の通り修正しました。
f:id:bluebirdofoz:20210628225530j:plain

メニューから[ビルド -> (プロジェクト名)のリビルド]を選択し、再ビルドを行います。
f:id:bluebirdofoz:20210628225541j:plain

動作確認

クライアントアプリを起動します。
[Connect]ボタンを押して、Azure Function を通して SignalR に接続できることを確認します。
f:id:bluebirdofoz:20210628225552j:plain

アプリを2つ立ち上げて[Broadcast]ボタンも正常に動作していることを確認します。
f:id:bluebirdofoz:20210628225604j:plain

長くなったので分けます。
次は HoloLens2 用クライアントアプリの作成です。
bluebirdofoz.hatenablog.com

AzureのSignalRServiceを使ってサーバからHoloLens2にデータを送信する その3(クライアントアプリの作成)

本日は Azure と HoloLens2 の技術調査枠です。
Azure の SignalRService を使ってサーバから HoloLens2 にデータを送信する方法を試したので作業記録を記事にします。
f:id:bluebirdofoz:20210627224717j:plain

前回記事の続きです。
bluebirdofoz.hatenablog.com

クライアントアプリの作成

Azure Function のAPIを実行し、SignalR からの通知を受信するサンプルのクライアントアプリを作成します。
初めに参照の記事と同様に WPF アプリケーションのプロジェクトを作成します

プロジェクトの作成

VisualStudio2019 を起動し、[新しいプロジェクトの作成]から[WPF アプリケーション(C#)]を選択します。
f:id:bluebirdofoz:20210627224744j:plain

プロジェクト名と作成ディレクトリを指定します。
f:id:bluebirdofoz:20210627224756j:plain

[ターゲットフレームワーク]には[.NET Core 3.1]を選択し、[作成]をクリックします。
f:id:bluebirdofoz:20210627224807j:plain

WPF アプリケーションのテンプレートプロジェクトが作成されます。
f:id:bluebirdofoz:20210627224819j:plain

参照の記事に合わせて MainWindow.xaml ファイルを編集します。
f:id:bluebirdofoz:20210627224831j:plain

MainWindow.xaml.cs ファイルも同様に編集して実行関数を追加します。
ただしデフォルトでは Microsoft.AspNetCore.SignalR.Client の参照がないため、エラーが表示されます。
f:id:bluebirdofoz:20210627224844j:plain

ライブラリ参照の追加

Microsoft.AspNetCore.SignalR.Client の参照を追加します。
メニューから[プロジェクト -> NuGetパッケージの管理]を選択します。
f:id:bluebirdofoz:20210627224857j:plain

[参照]タブを開き、[パッケージソース]に[nuget.org]を指定します。
[Microsoft.AspNetCore.SignalR.Client]を検索し、[インストール]を実行します。
f:id:bluebirdofoz:20210627224910j:plain

変更のプレビューダイアログとライセンスへの同意ダイアログが表示されるので確認して進めます。
f:id:bluebirdofoz:20210627224922j:plain
f:id:bluebirdofoz:20210627224935j:plain

これで Microsoft.AspNetCore.SignalR.Client の参照が追加できました。
f:id:bluebirdofoz:20210627224948j:plain

アプリケーションのビルド

MainWindow.xaml.cs ファイルに Azure Function へのアクセスURLを設定します。
f:id:bluebirdofoz:20210627225001j:plain

メニューから[ビルド -> ソリューションのビルド]を実行してビルドします。
f:id:bluebirdofoz:20210627225015j:plain

作成した exe ファイルを起動します。
f:id:bluebirdofoz:20210627225027j:plain

通知と受信の確認をするため、アプリを2つ起動して[Connect]ボタンをクリックします。
SignalR Service への接続が成功すると[Connected!]の文字列が表示されます。
f:id:bluebirdofoz:20210627225039j:plain

片方のアプリで[Broadcast]ボタンをクリックしてみます。
SignalR Service に時刻情報が通知され、両方のアプリに受信した文字列が表示されます。
f:id:bluebirdofoz:20210627225051j:plain

長くなったので分けます。
次は Authorization level を Function にした場合の設定方法です。
bluebirdofoz.hatenablog.com

AzureのSignalRServiceを使ってサーバからHoloLens2にデータを送信する その2(Azure Functionの関数作成)

本日は Azure と HoloLens2 の技術調査枠です。
Azure の SignalRService を使ってサーバから HoloLens2 にデータを送信する方法を試したので作業記録を記事にします。
f:id:bluebirdofoz:20210626013223j:plain

前回記事の続きです。
bluebirdofoz.hatenablog.com

Azure Functionの関数作成

今回は Azure Function の関数作成に VisualStudio2019 のテンプレートを利用します。
テンプレート利用のため、予め VisualStudioInstoller から[Azureの開発]をインストールしておきます。
f:id:bluebirdofoz:20210626013250j:plain

プロジェクトの作成

VisualStudio2019 を起動し、[新しいプロジェクトの作成]から[Azure Function]を選択します。
f:id:bluebirdofoz:20210626013316j:plain

プロジェクト名と作成ディレクトリを指定し、[作成]をクリックします。
f:id:bluebirdofoz:20210626013300j:plain

テンプレートの選択ダイアログが表示されるので[SignalR]を選択します。
今回は参照の記事に合わせて[Authorization level]に[Anonymous]、[Hub name]に[sample]を指定します。
f:id:bluebirdofoz:20210626013348j:plain

Tips

[Authorization level]に[Anonymous]を指定した場合、その関数はファンクションキー無しに URL へのアクセスのみで利用可能になるので取り扱いに注意が必要です。
docs.microsoft.com

[作成]ボタンをクリックすると、プロジェクトが作成されます。
SignalR Service への接続先を問い合わせるための negotiate 関数が自動で生成されています。
f:id:bluebirdofoz:20210626013406j:plain

次に SignalR Service に通知を投げる関数を実装します。
参照の記事と同様に broadcast 関数を追加しました。
f:id:bluebirdofoz:20210626013420j:plain

blog.xin9le.net

以下、参照記事からの抜粋です。

[FunctionName("broadcast")]  // 任意
public static async Task BroadcastAsync
(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest request,  // POST で投げることにする
    [SignalR(HubName = "sample")] IAsyncCollector<SignalRMessage> messages
)
{
    var data = await request.ReadAsStringAsync();  // 受け取ったデータを取り出す
    await messages.AddAsync(new SignalRMessage  // 出力バインディングを使って SignalR Service に投げ込む
    {
        Target = "Receive",  // 配信先の 'Receive' を呼び出す
        Arguments = new[] { data },  // Push 配信するデータ
    });
}

関数の発行

次に作成した関数を Azure Function に発行します。
f:id:bluebirdofoz:20210626013430j:plain

メニューから[ビルド -> (プロジェクト名)の発行]を選択します。
f:id:bluebirdofoz:20210626013444j:plain

公開先の選択ダイアログが表示されます。
[ターゲット]には[Azure]を選択します。
f:id:bluebirdofoz:20210626013457j:plain

[特定のターゲット]には[Azure Function App(Windows)]を選択します。
f:id:bluebirdofoz:20210626013510j:plain

[Functions インスタンス]には先ほど作成した Azure Function のインスタンスを選択して[完了]をクリックします。
f:id:bluebirdofoz:20210626014148j:plain

これで関数のビルドが実行されます。
[公開]タブが開くので、[発行]ボタンをクリックします。
f:id:bluebirdofoz:20210626013533j:plain

これで関数の発行が完了します。
f:id:bluebirdofoz:20210626013544j:plain

Azure Function のページで[関数]タブを確認すると、作成した関数を確認できます。
f:id:bluebirdofoz:20210626013827j:plain

[概要]タブから Azure Function の[URL]をアクセス先として取得しておきます。
f:id:bluebirdofoz:20210626013945j:plain

長くなったので分けます。
次はクライアントアプリの作成です。
bluebirdofoz.hatenablog.com