ORiN3を使ってデバイスにアクセスしてみる
はじめに
前回の記事でORiN3のセットアップを行い、GUIベースで簡単な動作確認を行いました。
今回は、C#でORiN3にアクセスしてみようと思います。
この記事では以下の流れで説明していきます:
- C#のプロジェクトの作成
- nupkgの設定
- サンプルプログラムを使ったデータアクセス
1. C#のプロジェクト作成
まずは、ORiN3を扱うためのC#プロジェクトを作成します。
Visual Studio 2022を使いますがVisual Studio Codeなど別のIDEでも構いません。
プロジェクトを新規作成
コンソールアプリのプロジェクトを新規作成します。
プロジェクト名はなんでも良いですが『ORiN3Sample』としました。
ORiN3のアクセスに必要なnupkgは.NET Standard2.1がターゲットになっています。
対応可能なフレームワークであればどれを選択しても良いですが今回は.NET8.0を選択しました。
作成ボタンをクリックしてください。
2. nupkgの設定
次は必要なnupkgを設定していきます。
NuGetパッケージマネージャーを開く
プロジェクトの依存関係をクリックしてNuGetパッケージマネージャーを起動します。
nupkeのインストール
参照タブで Message.Client.ORiN3 を検索して以下のnupkgをインストールします。
- Message.Client.ORiN3.Provider
- Message.Client.ORiN3.RemoteEngine
3. サンプルプログラムを使ったデータアクセス
次にサンプルプログラムを作っていこうと思います。
コードの自動生成
ORiN3の設定は ORiN3入門:環境構築ガイド+GUIツールで動かしてみる② で作成したプロジェクトを使います。
このような設定になっているはずです。
ORiN3 Configurator のオブジェクトエクスプローラー上でMockプロバイダを右クリックしてソースコード生成を選択します。
そうするとプロバイダ生成のコードがクリップボードにコピーされますのでそれをIDEに貼り付けてみてください。
自動生成されたMainメソッドの中に貼り付けましたがいくつか調整が必要です。
usingの部分をコードの上部に移動させたのと、Mainメソッドをasyncに変更しました。
この状態でORiN3プロバイダーの起動・終了ができるはずです。
トラブルシューティング
もしもうまくいかない場合は以下を確認ください。
プロキシの設定
Message.Client.ORiN3 はgRPCで ORiN3 Remote Engine や ORiN3 Provider と通信を行います。
これはHTTPの通信になりますのでプロキシが設定されていると意図した接続先につなげられないことがあります。
ORiN3 Remote Engineを別PCで起動している場合
ORiN3はセキュリティの都合上、デフォルト状態ではローカルホスト以外からの接続ができないようになっています。
別PCで起動している ORiN3 Remote Engine に接続する場合は適切な権限設定が必要です。
ControllerとVariableの起動
上記と同様にオブジェクトエクスプローラー上で右クリックしてコードを生成してください。
以下に生成した全コードを貼っておきます。
PulseWaveVariableにアクセスして500msごと取得した値をしコンソールに表示しています。
using Design.ORiN3.Provider.Core.V1.Telemetry;
using Message.Client.ORiN3.Provider.V1;
using Message.Client.ORiN3.RemoteEngine.V1;
namespace ORiN3Sample
{
internal class Program
{
static async Task Main(string[] args)
{
using var cts = new CancellationTokenSource();
// Connect to Remote Engine
using var remoteEngineChannel = Grpc.Net.Client.GrpcChannel.ForAddress("http://127.0.0.1:7103/");
using var remoteEngine = await RemoteEngine.AttachAsync(remoteEngineChannel, uint.MaxValue, cts.Token).ConfigureAwait(false);
// Launching Provider
var providerEndpoints = new ProviderEndpoint[] { new ProviderEndpoint(0, "127.0.0.1", 0, Array.Empty<byte>()) };
var telemetryEndpoints = new TelemetryEndpoint[] { };
var telemetryAttributes = new Dictionary<string, string> { };
var telemetryOption = new TelemetryOption(true, telemetryEndpoints, telemetryAttributes);
var extensions = new Dictionary<string, string> { };
var wakeupProviderResult = await remoteEngine.WakeupProviderAsync(
id: "643D12C8-DCFC-476C-AA15-E8CA004F48E8",
version: "1.1.0",
threadSafeMode: true,
endpoints: providerEndpoints,
logLevel: ORiN3LogLevel.Information,
telemetryOption: telemetryOption,
extension: extensions,
token: cts.Token).ConfigureAwait(false);
var providerPort = wakeupProviderResult.ProviderInformation.EndPoints
.Where(x => Uri.TryCreate(x.Uri, UriKind.Absolute, out _))
.Select(x => new Uri(x.Uri))
.First(x => x.Host == "127.0.0.1")
.Port;
// Attach RootObject
using var providerChannel = Grpc.Net.Client.GrpcChannel.ForAddress($"http://127.0.0.1:{providerPort}");
using var rootObject = await ORiN3RootObject.AttachAsync(providerChannel, uint.MaxValue, cts.Token).ConfigureAwait(false);
// Create object
var controllerObject = await rootObject.CreateControllerAsync(
name: "GeneralPurposeController",
typeName: "ORiN3.Provider.ORiNConsortium.Mock.O3Object.Controller.GeneralPurposeController, ORiN3.Provider.ORiNConsortium.Mock",
option: "{\"@Version\":\"1.1.0\"}",
token: cts.Token).ConfigureAwait(false);
// Connect
await controllerObject.ConnectAsync(cts.Token).ConfigureAwait(false);
// Create object
var variableObject = await controllerObject.CreateVariableAsync<bool>(
name: "PulseWaveBoolVariable",
typeName: "ORiN3.Provider.ORiNConsortium.Mock.O3Object.Variable.PulseWaveBoolVariable, ORiN3.Provider.ORiNConsortium.Mock",
option: "{\"@Version\":\"1.1.0\"}",
token: cts.Token).ConfigureAwait(false);
// Get value
for (int i = 0; i < 10; i++)
{
var value = await variableObject.GetValueAsync(cts.Token).ConfigureAwait(false);
Console.WriteLine(value);
await Task.Delay(500).ConfigureAwait(false);
}
// Delete object
await variableObject.DeleteAsync(cts.Token).ConfigureAwait(false);
// Disconnect
await controllerObject.DisconnectAsync(cts.Token).ConfigureAwait(false);
// Delete object
await controllerObject.DeleteAsync(cts.Token).ConfigureAwait(false);
// Shutdown Provider
await rootObject.ShutdownAsync(cts.Token).ConfigureAwait(false);
}
}
}
実行結果はこんな感じです。
関連情報(公式)