はつねの日記

Kinect, Windows 10 UWP, Windows Azure, IoT, 電子工作

M5Stackで.NET nanoFrameworkからセンサー使ってみた

前回

hatsune.hatenablog.jp

前回は、.NET nanoFrameworkでの開発準備とM5Stack Core 2での簡単なアプリの実行まで実施しました。
今回は、M5Stack Core 2のPORT Aと呼ばれる外部端子にセンサーを接続して、気圧や気温、湿度などを画面に表示してみたいと思います。

事前準備

センサーについて

この記事で使用するセンサーは、手元にあったM5StackユニットのENV-IIを使います。
M5Stackユニットは、M5Stack Core 2のPORT.A.I2C端子に接続できるセンサーです。
PORT.A.I2Cは、その名の通りI2Cと呼ばれるシリアスバス規格となります。
ENV-IIは、気圧センサーとしてBMP280、気温と湿度のセンサーとしてSHT30を内蔵したユニットとなります。
ENV-IIとM5Stack Core 2を接続し、更にM5Stack Core 2をUSBでPCに接続して、準備完了です。

Install the nanoFramework firmware

M5Stackに使われているESP32にはnanoFrameworkは標準インストールされていないので、nanoFrameworkをインストールします。

接続ポート番号の確認

USBでM5Stack Core 2をPCに接続したら、デバイスマネージャーで「CP210x」が接続されているポート番号を確認します。今回の環境では「COM4」が該当しました。

Flasherアプリケーションのインストール(インストール済の場合は不要)

OSの[スタート]メニューから「Developer PowerShell for VS2022」を起動します。

dotnet tool install --global nanoff

nanoFrameworkfファームウェアをインストール

今回使用するM5Stackは、M5Stack Core 2になります。
このM5Stack Core 2をターゲットにして「COM4」経由でnanoFrameworkをアップロードします。

nanoff --target M5Core2 --update --serialport COM4

Device Explorerでの接続確認

nanoFrameworkファームウェアをインストールしたあとにVisual Studioを起動してDevice Explorerをみると、「M5Core2 @ COM4」と表示されるようになります。

nanoFrameworkファームウェアは、インストールしたあとにnanoFramework以外の別イメージをM5Stack Core 2に転送(Burn)してしまうと消えてしまうので、Device Explorerに表示がないような場合は、再度、インストールをしてからVisual Studioを起動すれば表示されるようになります。

Visual Studioの準備

Visual Studioを機能拡張する

Visual Studioには.NET nanoFramework Extensionをインストールして機能拡張しておきます。
この機能拡張によりnanoFrameworkアプリのテンプレートが追加されます。
このテンプレートで作成したプロジェクトには、NuGetから自動的に「nanoFramework.CoreLibrary」ライブラリが追加されています。

「nanoFramework.M5Core2」ライブラリを追加する

今回は、M5Stack Core 2を使うので、「nanoFramework.M5Core2」ライブラリを手動でNuGetから追加します。

ここまでが、M5Stack Core 2を使うアプリ開発を行う上での共通の事前準備となります。

M5Stackで気圧表示(BMP280)

ライブラリの追加

.NET nanoFrameworkにはBMP280用のライブラリである「nanoFramework.Iot.Device.Bmxx80」がNuGetで提供されています。
.NET nanoFramrworkアプリケーションテンプレートで新規プロジェクトを作成したら、NuGetでBmxx80ライブラリを追加します。

BMP280から気圧を取得して画面に表示するC#コード

ENV-IIのI2Cアドレスを調べる

I2Cシリアル通信では、PORT.A.I2C端子につながっているセンサーから特定のセンサーを指定するために「アドレス」を指定します。
ENV-IIの中のBMP820と接続するためにアドレスに指定する値は、ENV-IIの仕様書をみると書かれています。
ENV II Unit with Temperature Humidity Environment Sensor (SHT30+BMP280) | m5stack-store

Description
ENV II is an environmental sensor which can sense temperature, humidity and atmospheric pressure. It integrates the SHT30 and BMP280 sensors and is programmed over the I2C protocol(SHT30:0x44, BMP280:0x76).

このアドレスを指定してI2C通信を行うことでBMP280より気圧値を取得できます。
nanoFrameworkでは、I2C通信用の「System.Device.I2c」クラスがあるので次のようなコードでI2C通信経路を確立できます。
gist.github.com

このコードは、「nanoFramework.M5Core2」ライブラリをNuGetから追加すると次のように簡単になります。
gist.github.com

センサー値を取得する

全体的なコードは次のようになります。
gist.github.com
センサー値の取得部分は次のところです

UnitsNet.Pressure pressure;
if (Bmp.TryReadPressure(out pressure))

[UnitsNet.Pressure」ライブラリは、「nanoFramework.IoT.Device.Bmxx80」ライブラリをNuGetで入れると自動的に追加されるBMP280で気圧を取得するためのライブラリです。
I2Cシリアル通信は、バイナリデータの送受信となりセンサー仕様のバイナリ形式から必要な数値形式に変換など地味にコード量が多くなる傾向にあります。
[UnitsNet.Pressure」ライブラリは、BMP280でのそのあたりを隠蔽して、更にヘクトパスカル表示(最近はミリバールとは言いません)のための単位変換もやってくれます。

M5Stackで気温と気圧表示

BMP280から気圧を無事取得できたので、次は、SHT30から気温と湿度を取得してみます。

ライブラリの追加

.NET nanoFrameworkにはSHT30用のライブラリである「nanoFramework.Iot.Device.Sht3x」がNuGetで提供されています。

SHT30から気温と湿度を取得して画面に表示するC#コード

ENV-IIのI2Cアドレスを調べる

ENV-IIのSHT30のアドレスは仕様書から「0x44」なのでそれを指定して通信を確立します。
gist.github.com
最近のC#では左辺の型がきまっているときはnewの後のクラス名を省略できるので下記のように書くこともできます。

Sht = new (M5Core2.GetI2cDevice(0x44))

センサー値を取得する

全体的なコードは次のようになります。
gist.github.com
センサー値の取得部分は次のところです

Console.WriteLine($"Temperature:{Sht.Temperature.DegreesCelsius:F} C");
Console.WriteLine($"Humidity:{Sht.Humidity.Percent:F} %");

M5Stack Core 2での動作

ENVIIから気圧、気温、湿度を取得するコードが完成したので、Visual Studioで[デバッグ]-[デバッグの開始]メニューでM5Stack Core 2への転送と実行を行います。

時間とセンサー値が1秒ごとに更新表示されます。

ENV-IIが入手できない

今回利用したENV-IIですが、残念ながら、2022年6月現時点では販売は終了しており、後継品のENV-IIIに代わっていました。
www.switch-science.com

ENV-IIとENV-IIIの違いを確認する

ENV-IIとENV-IIIの違いは気圧センサーがBMP280からQMP6988に変更されている点です。
そのため、ENV-II対応のプログラムからBMP280関連部分は変更が必要になります。

ENV-IIIのI2Cアドレスを調べる

I2Cシリアル通信では、PORT.A.I2C端子につながっているセンサーから特定のセンサーを指定するために「アドレス」を指定します。
ENV-IIIの中のQMP6988と接続するためにアドレスに指定する値をENV-IIIの仕様書から読み取ります。
ENV III Unit with Temperature Humidity Air Pressure Sensor (SHT30+QMP6988) | m5stack-store

I2C interface (SHT30:0x44 , QMP6988:0x70)

SHT30についてはENV-IIと同様に「0x44」ですが、QMP6988は「0x70」となります。

ENV-IIIのライブラリを調べる

SHT30については「nanoFramework.Iot.Device.Sht3x」ライブラリが使えますが、QMP6988を使うためのライブラリは2022年6月現時点ではNuGetに公開されていません。
そこで自作でQMP6988用のクラスを作成する必要があることが分かりました。

QMP6988のデータシートを読み解く

QMP6988用のクラスを作成するためには、必要なQMP6988の情報をデータシートで確認することになります。
https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/unit/enviii/QMP6988%20Datasheet.pdf
データシートを読んでみるとQMP6988は気圧以外にも気温が取得できるようです。この気温は、気圧の補正に使用します。
データシートには、そのほかにもQMP6988の気圧解像度(正確性)が0.06 Pa = 6 hPaであるなどの情報も記載されている。気圧解像度が6 hPaということは、6 hPa以下の精度は出ないということになります。

センサー値の理解

QMP6988はレジスタと呼ばれる1byte(=8bit)の領域を介して値のやりとりを行います。
データシートの「4.4 Implementing Register List」によればレジスタは全部で38個あります。

気圧データは0x07~0x09の3つのレジスタ、つまり3byte値で取得できます。
3byteの中のデータフォーマットには、22bitモード、23bitモード、24bitモードの3つのデータフォーマットがあります。
データ形式は、アドレスが小さい方に上位ビットが来る「BigEndian」形式となります。

センサーの生データは「符号なし24bitデータ」とのことで、データシートによれば24bitモードでは2の23乗をマイナスする必要があると書かれています。
このあたりのbitフォーマットからの数値化の方法も記載があり次のようにすればよいことが分かります。

Dp = ((PRESS _ TXD2) <<16) + ((PRESS _ TXD1) << 8) + (PRESS _ TXD0) − pow(2,23)

.NET nanoFrameworkには便利な関数が用意されておりシフト演算をしなくても「BigEndian」形式からuint型へ変換してくれます。

System.Buffers.Binary.BinaryPrimitives.ReadUInt32BigEndian(data) - Math.Pow(2, 23)

QMP6988の設定

QMP6988の設定初期は以下の通りです。この設定は、CTRL_MEASレジスタ(0xF4)により変更できます、

  • 出力モード:測定しない
  • パワーモード:Sleep


QMP6988には3種類の出力モードがあり、パワーモードをNormalにして、気温は22bitモード、気圧は24bitモードで出力したいときは、「0x1F」を設定します。
気温を22bitモードにしているのは、気圧補正用の気温のため精度はそれほど重要でないため一番低い解像度でよいからです。

パワーモードについて

パワーモードを変更すると計測と消費電力の関係は次のようになります。

  • Sleep:消費電力は最小ですが、測定はできません。
  • Force: 測定時だけ測定用に回路に通電し、測定が終わると必要最小限の消費電力に落とすモードです。
  • Normal:定期的に測定しつづけるモードです。測定間隔の初期値は1msとなります。

測定間隔は、IO_SETUPレジスタのt_standby領域で指定が可能で、1ms~4秒までの間で指定ができて、測定間隔が長いほどトータル消費電力は下がります。もし、4秒よりも長い測定間隔でよい場合は、パワーモードをForceにするのが適切です。

QMP6988用クラスのC#コード

I2Cシリアル通信を確立する

IC2シリアル通信の確立は、QMP6988変わっても同様に「M5Core2.GetI2cDevice(0x70)」で実現できます。
BMP280用ライブラリと同様に、この戻り値をQMP6988クラスに渡します。
gist.github.com

モードを指定する

解像度やパワーモードを指定するためには、CTRL_MEASレジスタ(0xF4)に1バイトのデータを書き込むことで実現します。
gist.github.com

気圧を読み取る(3バイト領域)

QMP6988が気圧をレジスタに代入するタイミングは2つあります。
パワーモードがNormalの場合は、t_standbyに設定された間隔で自動的にレジスタに気圧が記録されますので、値を取得するときはレジスタにすでに格納されている値を読み取るのみです。
Forceの場合は、レジスタ読み取り時に気圧を測定してレジスタに格納します。
レジスタから値を取得するには、

  1. レジスタアドレスをWriteする
  2. 返却サイズに応じたバイト配列を指定してReadする

ことで3バイトの気圧データを取得できます。

気圧を読み取る(4バイト領域)

しかし、C#の変数で3バイト長の変数は存在しないため、少しおさまりが悪いです。そこで4バイト領域に3バイト分のデータを読み込みます。
gist.github.com
このコードの中で少し馴染みの薄い部分は次のところでしょう。

this.I2c.Read(readBuff.Slice(1))

この記述により合計で3バイトのデータをbyte[4]の2バイト目以降に受信します。
こうして得られたbyte[4]のバイト配列は次のコードでuint型の数値にできます。

System.Buffers.Binary.BinaryPrimitives.ReadUInt32BigEndian(data)

気圧の生データを実地に変換

取得できた気圧の生データは、そのままでは正しい気圧値を表していないため、気温と合わせて補正計算をしてから16分の1の数値にします。
gist.github.com
BMP280もそうでしたが気圧センサーのデータ取り扱いの肝は「ConvTx02e」「Pressure02e」などで記載している補正関数になりますが、今回は説明が冗長になるので詳細は割愛します。

ENV-IIIから気圧、気温、湿度を取得して画面に表示するC#コード

QMP6988用のクラスが作成できたら、それを使ってENV-II用のコードを書き換えてENV-III用のアプリを作成しましょう。

ENV-IIIのI2Cアドレスを調べる

ENV-IIIのQMP6988のアドレスは仕様書から「0x70」なのでそれを指定して通信を確立します。

Qmp = new (M5Core2.GetI2cDevice(0x70))

センサー値を取得する

全体的なコードは次のようになります。
gist.github.com
センサー値の取得部分は次のところです

Console.WriteLine($"DateTime:{DateTime.UtcNow:yyyyMMdd HHmmss}");
Console.WriteLine($"Pressure:{Qmp.CalcPressureHectopascals():F} hPa");
Console.WriteLine($"Temperature:{Sht.Temperature.DegreesCelsius:F} C");
Console.WriteLine($"Humidity:{Sht.Humidity.Percent:F} %");

M5Stack Core 2での動作

ENV-IIIから気圧、気温、湿度を取得するコードが完成したので、Visual Studioで[デバッグ]-[デバッグの開始]メニューでM5Stack Core 2への転送と実行を行います。

時間とセンサー値が1秒ごとに更新表示されます。

最後に

M5Stack Core 2にENV-IIユニットやENV-IIIユニットを繋いでC#で取得・表示するコードを紹介しました。
ユニットに使われているセンサーチップに対応したライブラリがNuGetにあると非常に簡単にコードが書けます。
そしてライブラリがない場合もデータシートの読みポイントさえ見つけることができれば、バイナリーデータ送受信とフォーマット変換のコードへとデータシートの内容を読み落としていく工程は、簡単とはいえませんが不可能ではありません。
NuGetにライブラリがないからと言って使うのをあきらめたりせず、データシートを読み解きながら実装していくのも、センサー系開発の醍醐味です。

センサーの取り扱いが整理できて来たので、次回は、今回取得したセンサーデータをAzureに送信するコードに挑戦します。
hatsune.hatenablog.jp

M5Stackで.NET nanoFramework動かしてみた

やっぱりSoCにアプリ組み込んで動かすのが好きです。
そして、それがC#だともっと好き(書きたいことが書きたいように書けるから)。

昨年は、Arduinoを開発環境にしてM5Stackのアプリを色々作成していました。
少しでも使いやすい開発環境でということでVisual Studio Codeなども活用しました。

そんなM5Stackアプリ開発ですが、気づいてみたら、.NET nanoFrameworkで開発できるようになっていました。Arduinoとの違いは、.NET nanoFrameworkを使えばC#でコードが書けるという点です。すごい!

そもそも

M5 Stackとは

M5Stackは、ESP32というbluetoothWi-Fiを内蔵するSoCを使って、それに320x240のTFTカラー液晶、microSDカードスロット、スピーカーを組み合わせたコンパクトで便利な開発モジュールになります。
ESP32はArudino環境で開発ができるのでM5Stackで動作するアプリもArduino環境で開発ができます。
M5Stackには様々な拡張モジュールがあり、M5Stack Coreと呼ばれるM5Stack本体に拡張モジュールを積み重ねていくことでいろいろな機能が拡張ができます。

M5Stack Core 2とは

今回使うM5Stack Core 2は、M5StackのCore機能を改良した2022年6月時点での最新世代(第二世代)のCoreデバイスとなります。
www.switch-science.com
M5Stack Core 2のハード仕様などは下記の過去記事が参考になります。
hatsune.hatenablog.jp

.NET nanoFrameworkとは

.NET nanoFrameworkは、ESP32などのMCU(マイクロコントローラユニット)などの組込み用デバイス向けに.NETアプリの作成を可能にする無償のオープンソースプラットフォームです。
C# + .NET 6でデスクトップアプリを作成した経験が組込みシステム開発で活かせることを想定しているそうです。

.NET Core IoTとの違いは?

.NET環境での小型デバイス向けの開発には、.NET Core IoTと呼ばれているものもあります。
.NET Core IoTは、.NET Core+IoT向けライブラリで構成されています。
.NET Coreを動作させるので組込みといってもある程度のリソースが必要で、ターゲットとするハードは、Raspberry Piが想定さてています。
一方、.NET nanoFrameworkは動作環境でもあり、.NET Coreのランタイムではなく、.NET nanoFrameworkのランタイムでアプリが動作します。その代わり、組込み用デバイスでは不要な部分がなく、.NET Core IoTよりも更に小さなリソースで動作します。

事前準備

.NET nanoFramework Extensionを追加

.NET nanoFrameworkのプロジェクトをVisual Studioで作成できるように、Visual Studioを拡張(機能追加)しましょう。
そのために使用する拡張機能が「.NET nanoFramework Extension」です。
marketplace.visualstudio.com
Visual Studio 2022を起動したら、[拡張機能]-[拡張機能の管理]メニューで管理ウィンドウを開いてから「nano」で検索して.NET nanoFramework Extensionを探し出して適用します。

Install the nanoFramework firmware

M5Stackに使われているESP32にはnanoFrameworkは標準インストールされていないので、nanoFrameworkをインストールします。

接続ポート番号の確認

USBでM5Stack Core 2をPCに接続したら、デバイスマネージャーで「CP210x」が接続されているポート番号を確認します。今回の環境では「COM4」が該当しました。

Flasherアプリケーションのインストール

OSの[スタート]メニューから「Developer PowerShell for VS2022」を起動します。

dotnet tool install --global nanoff

nanoFrameworkfファームウェアをインストール

今回使用するM5Stackは、M5Stack Core 2になります。
このM5Stack Core 2をターゲットにして「COM4」経由でnanoFrameworkをアップロードします。

nanoff --target M5Core2 --update --serialport COM4

正常に動作すると次のようなログが表示されます。
gist.github.com

M5StackでHelloWorld

M5Stackアプリのプロジェクトを作成

.NET nanoFrameworkのテンプレートでプロジェクトを新規作成

機能拡張がうまくいくとVisual Studoの新規プロジェクト作成のテンプレートに「.NET nanoFramework」のテンプレートが追加されています。

まずは、「HelloWorld」というプロジェクト名で新規プロジェクトを作成して、M5Stack Core 2の液晶画面に「Hello World」と表示するアプリを作ってみます。

Device ExplorerでM5Core2を選択

プロジェクトが作成されたら、Device Explorerを開いてM5Core2との接続を確認します。
Device Explorerは、Visual Studioの「検索」機能から開くのが艦隊です。

テンプレートの初期コードを実行

M5Stack Core 2との接続や事前準備が正常に終わっていると、新しいプロジェクトを作成したときに自動生成されているコードのビルドおよび実行が正常に行われます。
自動生成コードは「Debug.WriteLine("Hello from nanoFramework!");」が実行される簡単なコードなので、実行が成功するとイミディエイトウィンドウに「Hello from nanoFramework!」と表示されます。

M5Stack Core 2の画面に「HelloWorld」

M5Stack Core 2用のライブラリを追加

M5Stack Core 2の画面などハードウェアにアクセスするために、M5Stack Core 2用のライブラリを追加します。

初めてのM5Stack C#プログラミング

M5Stackの画面に文字を表示する簡単な方法は「nanoFramework.M5Stack.Console.WriteLine」メソッドを使う方法です。
Console.WriteLineと書くとSystem.Consoleと名前が重複するのでusingでConsoleはnanoFramework.M5Stack.Consoleのことであることを宣言してあります。
gist.github.com

M5Stack Core 2のボタンに反応するように拡張

起動して「HelloWorld」と表示されるだけでは味気ないので、M5Stack Core 2についている3つのボタンをクリックしたら画面にボタンの種類を表示するようにしてみましょう。
M5Stack Core 2用のライブラリでボタンクリックイベントは「TouchEvent」としてイベントが発生します。
そして、そのイベント引数から3つのボタンのどれがクリックされたかをif文で判定します。
gist.github.com
イベントハンドラーを書き始めるとC#っぽい感じがすごくでてきますね。

Visual Studioから切り離してM5Stack Core 2だけで動作させる

Visual Studioデバッグ実行をとめるとM5Stack側も動作がとまってしまいます。
M5Stackだけで動作させるには、M5Stackで電源OFF/ONをしてアプリをリスタートしてあげると実行できます。

まとめ

ファームウェアの転送など少しだけ事前準備が必要ですが、比較的簡単に使える環境が整ってきた感じがします。
ファームウェアは1度実施すれば(更新はあとであるかもですが)、毎回する必要はないのですが、Device Explorerでつながっているかを確認するのは忘れがちで、デバッグ実行したときなどに「あれ?転送されない」と焦ることがあるので注意しましょう。
また、Device Explorerで「disable」すると、再度、enableするためにはデバイスマネージャーの方で該当COMポートを「無効」にして「有効」にしないといけないので、「なんだろ?」とか思ってDevice Explorerでdisable device watchesしないように注意しましょう。

次回

次回は、ENV.II SENSORを繋いで気圧を画面に表示するアプリをC#で作成します。
hatsune.hatenablog.jp

Azure CognitiveServices TextAnalyticsの「テキスト要約」をクライアントアプリから使ってみる(REST API編)

前回:
hatsune.hatenablog.jp

前回は、AzureポータルでTextAnalyticsを有効にして、Azure.AI.TextAnalytics SDKを使って「テキスト要約」を行うクライアントアプリの動作を確認してみました。
今回は、クライアントアプリからREST APIにて同様の動作を実現してみます。

準備

.NET 6ベースのWPFアプリとしてクライアントアプリを作成します。

新しいプロジェクトの作成

Visual Studio 2022で、新しいプロジェクトの作成で「WPFアプリケーション」のテンプレートを選択すると、.NET Frameworkベースではなく.NET 6ベースのWPFアプリが作成できます。
名前は「TextSummarizationAPISample」と名付けることにしましょう。

コードを記述

サンプルコードは、MVVMデザインパターンで作成しているので、画面はViewsフォルダ配下に「MainWindows.xaml」として記述し、REST APIを呼び出すロジックはModelsフォルダ配下に「TextSummarizationModel.cs」として記述します。

画面を作成

MVVMの良いところは、ViewとModelが分離できるところです。前回のSDKからの変更はModelの差し替えだけになるので、画面については、SDKのサンプル画面と同じく「入力欄」「実行ボタン」「出力欄」として、XAMLコードなどは名前空間だけかえてそのままコピペしてきます。名前空間変更前のものを再掲しておきます。
gist.github.com
このXAMLのx:classとxmlns:localを「TextSummarizationSDKSample」から「TextSummarizationAPISample」に変更します。

ロジックを作成

TextSummarizationModelクラスとしてREST API呼び出し部分を記述してみましょう。
gist.github.com
「your key」や「your resourcename」のところは、AzureでTextAnalyticsを有効化したときに生成されたキーとリソース名を設定します。
SDKのときよりもかなり複雑なコードになっています。
最初にREST APIのBODYとしてパラメタをJSON文字列として設定するためのクラスにパラメタを設定しています(9~39行目)。
67行目でPostによりREST APIをたたいていますが、この戻り値が要約結果ではありません。
72行目で取得できるのは、要約結果を得るためのjob番号付きURLです。
86行目では、72行目で得られたob番号付きURLを指定して要約結果をGetしています。
もちろん非同期実行ですから、Azure側で要約が完成して初めてSendAsycメソッドは値を返します。
そして、97行目から100行目で戻ってきた要約(今回は3文)を取得しています。

なお、上記には載せていませんがJSON形式とやり取りするためのクラス定義も必要です。

実行

対象のテキストを入力

Language Studioで試したように現在開催されているMicrosoft Build 2022のBook of NewsにあるAzureAIの説明を要約してみましょう。
news.microsoft.com
場所は、「1.1 Azure AI」の部分にしてみましょう。

実行結果

[Exec]ボタンをクリックして少し待つとテキスト要約結果が表示されます。

Microsoft Azure AIは、開発者が高品質なモデルをAPIとしてデプロイし、言語機能をより効率的かつ責任を持ってアプリに注入できるように、Azure Cognitive Servicesに2つのアップデートを導入します。
Azure Cognitive Serviceの1つであるAzure OpenAI Serviceは、現在プレビューで利用可能です。
Azure Cognitive Service for Languageは、文書や会話の要約を提供する新機能で、開発者が文書やコンタクトセンターの通話に含まれる重要な情報(通話理由や解決策など)を迅速に表面化できるよう支援します。

まとめ

TextAnalytics用のREST APIを使ってテキスト要約を行うクライアントアプリを作成してみました。
同じ文章を入力すればSDK版と同じ結果が当たり前ですが得ることができました。
こうやって記載してもるとREST APIに比べて、SDKが使いやすいので非常にシンプルなコードで実装できるのが分かってもらえたら嬉しいです。

Azure CognitiveServices TextAnalyticsの「テキスト要約」をクライアントアプリから使ってみる(SDK編)

前回:Azure CognitiveServices TextAnalyticsでテキスト要約を試してみる - はつねの日記

前回は、AzureポータルでTextAnalyticsを有効にして、Language Studioで「テキスト要約」動作を確認してみました。
今回は、クライアントアプリから前回有効にしたTextAnalyticsにつないでみましょう。

準備

.NET 6ベースのWPFアプリとしてクライアントアプリを作成します。
TextAnalyticsとの接続には、Azure.AI.TextAnalytics SDKを使います。
まずは、そのために準備として、Visual Studioで新しいプロジェクトを作成してNuGetから必要なライブラリを取得しましょう。

新しいプロジェクトの作成


Visual Studio 2022で、新しいプロジェクトの作成で「WPFアプリケーション」のテンプレートを選択すると、.NET Frameworkベースではなく.NET 6ベースのWPFアプリが作成できます。
名前は「TextSummarizationSDKSample」と名付けることにしましょう。

NuGetからSDKの取得

Azure.AI.TextAnalytics SDKをNuGetから取得しましょう。
www.nuget.org
ソリューションエクスプローラーでプロジェクトファイルを右クリックして[NuGetパッケージの管理]メニューでNuGetパッケージマネージャーを起動して、Azure.AI.TextAnalytics SDKをプロジェクトに追加します。

この時に注意しないといけないのは、(2022年6月4日現在)テキスト要約は「プレビュー」機能なので、NuGetから取得するAzure.AI.TextAnalytics SDKもプレリリース版が必要な点です。

そこで、「プレリリースを含める」をチェックして、プレリリース版の最新を取得してきます。
現時点でのプレリリース版は5.2.0-beta3ですので将来的に5.2.0が正式版となるまではプレリリース版を追加するようにしましょう。

コードを記述

サンプルコードは、MVVMデザインパターンで作成しているので、画面はViewsフォルダ配下に「MainWindows.xaml」として記述し、TextAnalytics APIを呼び出すロジックはModelsフォルダ配下に「TextSummarizationModel.cs」として記述します。

画面を作成

サンプルなので「入力欄」「実行ボタン」「出力欄」のシンプルが画面を作成してみます。
gist.github.com

ロジックを作成

TextSummarizationModelクラスとしてAPI呼び出し部分を記述してみましょう。
gist.github.com
「your key」や「your resourcename」のところは、AzureでTextAnalyticsを有効化したときに生成されたキーとリソース名を設定します。

実行

対象のテキストを入力

Language Studioで試したように現在開催されているMicrosoft Build 2022のBook of NewsにあるAzureAIの説明を要約してみましょう。
news.microsoft.com
場所は、「1.1 Azure AI」の部分にしてみましょう。

実行結果

[Exec]ボタンをクリックして少し待つとテキスト要約結果が表示されます。

Microsoft Azure AIは、開発者が高品質なモデルをAPIとしてデプロイし、言語機能をより効率的かつ責任を持ってアプリに注入できるように、Azure Cognitive Servicesに2つのアップデートを導入します。
Azure Cognitive Serviceの1つであるAzure OpenAI Serviceは、現在プレビューで利用可能です。
Azure Cognitive Service for Languageは、文書や会話の要約を提供する新機能で、開発者が文書やコンタクトセンターの通話に含まれる重要な情報(通話理由や解決策など)を迅速に表面化できるよう支援します。

まとめ

TextAnalytics用のSDKを使ってテキスト要約を行うクライアントアプリを作成してみました。
SDKが使いやすいので非常にシンプルなコードで実装できるのが分かってもらえたら嬉しいです。
次回は、今回作成したコードをベースにしてTextAnalytics APISDKではなくREST APIとして呼び出す方法について説明する予定です。
TextAnalytics APIを直に呼び出すことで更に理解が進むと思いますし、SDKが提供されていない環境から使うときのサンプルになればと思っています。

Azure CognitiveServices TextAnalyticsでテキスト要約を試してみる

Microsoft Build 2022が日本時間の2022/05/25 00:15から始まりました。
そのオープニングセッションでサティアCEOが話している内容で「~テキスト要約して~」と話しているところがありました。
Cognitive Servicesでテキスト要約とかできたんだっけ?と思ったので調べてみたらできるみたいですね。

Azure側の準備

Azureマーケットプレイスから探す

リソースを作成するで「TextAnalytics」と検索するとマーケットプレイスからMicrosoftが提供している「テキスト分析」を検索できます。

リソースを作成する


[作成]をクリックすると「追加機能の選択」に移動します。URL直指定だといきなり「追加機能の選択」に飛べます。

追加機能の選択


もしURL直でここまで行きたい場合は、次のURLからも作成を開始できます。
https://portal.azure.com/#create/Microsoft.CognitiveServicesTextAnalytics
検索で似たようなものから探すよりもURL直の方が確実なので好きです。
「テキスト要約」は基本機能にあるので、特に追加機能は選ばずに進めましょう。

TextAnalytics の作成


日本リージョンも選べますし、無料プラン(月上限5000呼び出し)もありますね。
「法的条項」や「責任ある AI 通知」にもチェックをいれて[確認と作成]クリックして検証が通ったら、[作成]をクリックと進んでいきましょう。

Language Studioで試す

Azure側でテキスト要約のリソース(API)の準備ができたので、次はクライアント側というのが従来のステップになりますが、最近のAzureではAPIを試す機能も充実しています。
テキスト要約も「Language Studio」で手軽に試すことができます。
https://language.cognitive.azure.com/home

試すリソースを指定

Language Studioにアクセスするとどのリソースで実行するかの聞かれますので、サブスクリプションやリソース名などを指定します。

Summarize textをTry it outする


翻訳がされていないツールなので「テキスト要約」を試すためには、「Summarize text」のトライを選びます。
UIは日本語化されていませんが、もちろん、対象言語として日本語もサポートしています。

日本語文章を要約する

現在開催されているMicrosoft Build 2022のBook of NewsにあるAzureAIの説明を要約してみましょう。
news.microsoft.com
テキスト要約は5000文字まで1度に要約できますので、要約の効果がわかりやすいように1000文字以上は対象テキストとしてみましょう。

入力データを設定したら、少し下にスクロールして[Run]をクリックします。

要約を確認する

実行結果は、人が見やすいように成形されたResultと、APIからの戻り値であるJSONの2つの形式で表示されます。
まずは、ResultのSummaryを確認してみます。

結果は約220文字となり、元の文章が約1200文字でしたので、元の文章の約20%に要約されています。
Original text欄を見ると文章のどこの文をチョイスして要約したかが分かりやすく表示されています。

これをみると1文の中を要約してというよりも、全体の中からキーとなる文をランク付けして上位(今回は)3つ選んで要約結果としているようです。

APIの戻り値を確認する

実行結果をJSON形式で確認してみましょう。

結果はsentencesというJSON配列に返却されます。今回は3つにしているので配列要素は最大で3つになります。
sentencesの各要素は「text」「rankscore」「offset」「length」となっており、それぞれ「該当文」「重要度スコア(0~1)」「文先頭からの位置」「文字数」となります。

まとめ

最近のAzureは、アプリ作らなくても確認するためのページが用意されていて、すぐにAPIの動作確認ができるのがとても良いですね。
1文の中まで要約はしてくれないので、なんとなく日本人が考える「要約」というイメージと若干差異があるかもしれませんが、長文の中から重要なセンテンス3文を探してきてくれると考えると使い道はいろいろ広がりますね。

BFG Repo-CleanerをWindowsで使って、gitリポジトリからファイルを削除する

Gitリポジトリから不要なファイルを削除したいような場合、直前ならばまだしも過去のコミットから削除しようとすると大変です。
そんな時に便利なのが「BFG Repo-Cleaner」です。
github.com

検索すればネット上にいろいろ情報はありますが、「あれ?Windowsのときはどうするんだ?」と検索結果を読みながら若干手探りなところがあったので、忘備録として記載しておきます。

前提

  • Visual Studio 2022を使っていて、OpenJDKもインストール済

  • SourceTreeと使っている(Git for Windowsなどでもよい)

背景

リモート側を別の場所に移行する必要に迫られてローカルリポジトリをpushしようとしたところ、過去のコミットで大きなファイル(その後はそのファイルはいらなくなったので削除もコミットされている)があるということでpushが失敗してしまいました。
Git LFSが使うという方法もあるのですが、いらないファイルなので該当ファイルを削除してからPushする方法をとりたい。

悩んだポイント

Windowsではbfgの実行はどこですればいいのか?

手順

事前準備

事前にGitリポジトリをcloneしておくと万が一失敗したときにリカバリーできるそうです。

bfgのダウンロード

GitHubのBFG-Windowsリポジトリのリリースページからbgfのjarファイルをダウンロードします。
2022/05/09時点では1.13.0が最新です。
Release BFG-1.13.0 (2020-01-08) · wjk/BFG-Windows · GitHub

Open in Terminal

Visual Studioで該当ソリューションを右クリックして「Open in Terminal」を開きます。

これでソリューションのルートフォルダで「開発者用PowerShell」が起動できます。

java -jar c:\Users\hatsune\Downloads\bfg-1.14.0.jar --delete-files hogehoge.a .git

と入力すれば、ソリューションフォルダ直下の「.git」フォルダの内容を参照してリポジトリから「hogehoge.a」ファイルを削除してくれます。
正常に動作した場合は最後に次のように表示されます。

BFG run is complete! When ready, run: git reflog expire --expire=now --all && git gc --prune=now --aggressive

2つのgitコマンド、git reflog expireと git gcを実行するように即されていますね。

後処理

次に、ここがキモなのですが、「開発者用PowerShell」からいったん離れて「Git for Windows」や「SourceTree」などのコマンドプロンプトを開いて次のコマンドを実行します。

$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
Enumerating objects: 24347, done.
Counting objects: 100% (24347/24347), done.
Delta compression using up to 4 threads
Compressing objects: 100% (23104/23104), done.
Writing objects: 100% (24347/24347), done.
Total 24347 (delta 18601), reused 4215 (delta 0), pack-reused 0
Removing duplicate objects: 100% (256/256), done.

リモートにpush

これであとはリモートにpushします。

$ git push -u origin master

リモートとローカルのリポジトリの整合性がとれないので怒られると思うので「-f」で強制プッシュします。

$ git push -f

まとめ

パスをきちんと設定しておけばよいのかもしれないけれど、「開発者用PowerShell」と「Gitツールのターミナル」の二刀流でサクッとやってしまうのもいいのかなと思いました。

転生先で捨てられたので、もふもふ達とお料理します~お飾り王妃はマイペースに最強です~

I was abandoned in my reincarnation, so I'll cook with the fluffers - the ornamental queen is the strongest at her own pace!

amzn.to
The work introduced here follows the pattern of gaining allies through cooking, which is common in otherworldly reincarnations. The combination of this with a love of "Mof-Mof" makes for a lighthearted success story that moves along quickly and smoothly.
This work has been changed to "R" from the second volume.

amzn.to
If you start reading from "R", there is no introduction and you will be confused by the sudden development, so I suggest you start reading from "without R".
The "R" version has a more "Honwaka" style, so it is suitable for those who prefer the style of "R".

転生先で捨てられたので、もふもふ達とお料理します~お飾り王妃はマイペースに最強です~

amzn.to

今回紹介する作品は、異世界転生にありがちの料理で周りを味方につけていくパターンの作品です。そこに「もふもふ」好きという要素もかけ合わさって、さくさくと進むサクセスストーリーとしても軽快に話が進んでいきます。
こちらの作品、2巻目からは「R」としてコミカライズされる方が変更になっております。
amzn.to
「R」から読み始めると導入部分がなくて、いきなりな展開にとまどってしまうので、「Rなし」から読み始めるといいと思います。
そして、「R」の方の絵柄の方がより「ほんわか」していますので、そちらの絵柄がより好みの人向けの作品です。