プロデルでネットワーク伝送量ガジェットを作る

今回は、プロデルでパフォーマンス計測ガジェットを作ってみます。プロデルではWMI種類を使ってCPUやメモリ、ネットワークアダプタ(Wi-Fiなど)の通信量が得られます。今回はその中でも、ネットワーク伝送量を測定してその情報をキャンバスを使った折れ線グラフとして表示するツールを作ってみます。

Windows Vista時代には、デスクトップガジェットというツールがあり、画面のサイドに時計やカレンダー、メモリやCPU使用率を確認するための小さな小窓を表示できました。セキュリティ上の懸念からWindows 10の正式な機能としては廃止されましたが、プロデルではWindowsアプリを作れますので、システム情報に関連したガジェットを作ってみることにします。

WMIを使ってネットワーク伝送量を得るには

PCの通信状態は、WMI(Windows Management Instrumentation)を使ってネットワークアダプタの情報を得ることで調べることができます。ネットワークアダプタの情報を取得するには、「WMI」種類を使います。

WMIでは目的の情報を取得するためにSQLのようなクエリを指定します。指定できるクエリの書き方は、検索エンジンで検索すると資料が多数みつかります。

今回必要な総送受信量を調べるためのプログラムは、次の通りです。

WMIから「SELECT CurrentBandwidth, BytesReceivedPersec, BytesSentPersec FROM Win32_PerfRawData_Tcpip_NetworkInterface」で取得して結果リストとする
結果リストのすべてのオブジェクトについてそれぞれ繰り返す
	オブジェクトのすべての要素についてそれぞれ繰り返す
		もし要素の名前は、「BytesReceivedPersec」なら
			「総受信量=[要素の値]」を報告する
		他でもし要素の名前は、「BytesSentPersec」なら
			「総送信量=[要素の値]」を報告する
		他でもし要素の名前は、「CurrentBandwidth」なら
			「速度=[要素の値]」を報告する
		もし終わり
	繰り返し終わり
	繰り返しから抜け出す
繰り返し終わり

なお、BytesReceivedPersecとBytesSentPersecは、英語の表記とは異なり、実際には、それぞれ起動時からの総受信量と総送信量が得られる仕様のようです。それぞれ単位は、バイト(Byte)です。

キャンバスを使ってグラフを描く

ガジェットでは、1秒あたりの通信量を折れ線グラフとして表示させることにします。折れ線グラフは、横軸が時間で縦軸が通信量を表します。送信量と受信量はそれぞれ別のグラフで重ね合わせて表示させます。

キャンバスでは、直線や文字、図形などの基本的な要素を描くことができます。ただ今回描きたいグラフ図形は、標準では用意されていませんので、基本的な図形を組み合わせて自分で描くことにします。

グラフを描くには、連続線図形を使います。連続線図形は、指定した複数の座標を順番に直線で結んだ図形です。測定値を点の座標に置き換えて、その座標を順番に連続線図形に指定すれば、グラフができます。

グラフ値から点の座標を計算する

グラフ値から点のY座標を計算するには、次のような比率計算をします。30秒間での最大値がキャンバスの高さと同じになるように、比率を計算します。

グラフ値 : (点の高さ) = 最大値 : キャンバスの高さ

ただ、グラフ値から点の高さを求めるときは、Y軸の方向を考慮しなければなりません。キャンバスの座標系は、左上が原点となっていて、下方向へY軸の値が大きくなります。一方、折れ線グラフのY座標は、グラフ図の底(画面下側)が0となり、上方向に大きくなりますので、キャンバスのY座標とは逆です。

そのため、描く際の実際のY座標は、求めた値にキャンバスの高さを足してグラフ値の分だけ引いた値とすると正しく描かれます。つまり次のような比率になります。

グラフ値 : キャンバスの高さ - 点の座標値(y軸) = 最大値 : キャンバスの高さ

この比率を「点の座標値(y軸)=」となるように式に置き換えてから、プログラムにすると次のようになります。

(1-グラフ値リスト(番号)/最大値)*実質大きさの高さ

「折れ線グラフ図形」種類の定義

今回はグラフを描くための「折れ線グラフ図形」種類を定義して、複数のグラフを同時に扱いやすくします。「折れ線グラフ図形」種類は「子キャンバス」種類を継承して使うことにします。子キャンバスを継承するとキャンバス上に描く図形を自分で定義することができ、複雑な図形を1つの図形部品として扱えるようになります。

グラフの最大サンプル数(横軸の目盛りの数)は、30個とします。グラフには、測定した値を最大サンプル数を上限に記録していきます。

「グラフ値リスト」配列には、測定値(単位Kbps)を記録しておき、「座標値リスト」配列には測定値と子キャンバスの大きさから計算した、グラフの点の座標(ピクセル単位)を格納します。この2つの配列を用意した理由は、過去30秒の測定での最大値が変化した時に、キャンバスの高さが最大値と同じになるように座標を再計算できるようにするためです。

折れ線グラフ図形とは
  子キャンバスを継承する
  +サンプル数=30
  +グラフ値リスト={}
  +最大値=100
  +座標値リスト={}
  はじめ(キャンバス1)の手順=(キャンバス1)
    連続線を描いてグラフ線とする
      その線色を青に変える
      その太さを1に変える
      その点は、グラフ値リスト
    更新する
  終わり
  
  自分を更新する手順
    もし最大値が0なら最大値は、100
    単位幅は、実質大きさの幅/サンプル数
    座標値リスト(1)は、{0,実質大きさの高さ}
    番号を1からグラフ値リストの個数まで増やしながら繰り返す
      座標値リスト(番号+1)は、{(番号-1)*単位幅,(1-グラフ値リスト(番号)/最大値)*実質大きさの高さ}
    繰り返し終わり
    グラフ線の点は、座標値リスト
    グラフ線に{(番号-1)*単位幅,実質大きさの高さ}を加える
  終わり
  自分に【値】を加える手順
    グラフ値リストに値を加える
    個数は、グラフ値リストの個数
    もし個数がサンプル数より大きいなら
      開始番号は、個数-サンプル数
      グラフ値リストは、グラフ値リストの(開始番号+1)番目からサンプル数個切り出す
    もし終わり
  終わり
  線色を設定する手順
    グラフ線の線色を設定値に変える
    背景色という色情報(設定値)を作る
    背景色のアルファは、50
    グラフ線の背景色を背景色に変える
  終わり
終わり

「折れ線グラフ図形」種類のそれぞれの定義の説明をまとめました。

変数名/手順名説明
サンプル数記録する測定値の数(秒数)
グラフ値リスト測定した値の配列 (最大要素数はサンプル数)
座標値リスト折れ線グラフの点の座標
(最大要素数はサンプル数、ピクセル単位)
最大値グラフに表示できる最大値の値
更新する (手順)グラフ値リストの値に合わせて連続線図形を更新します。
加える (手順)グラフ値リストに値を加えます。
線色 (設定項目)グラフの線の色を設定します

「線色」設定項目では、連続線図形の線の色を設定することに加えて、折れ線グラフを見栄えを良くするために、連続線図形の塗りつぶし色を半透明にします。半透明にすることで、送信と受信とで2つのグラフを重ね合わせた時に図が潰れてしまわないようにしています。

半透明で塗りつぶすには、「色情報」種類を作り「アルファ」設定項目の値を0から100までの間に設定します。「色情報」種類は、値型の種類ですので、色や透明度を変えるには、新しく「色情報」のオブジェクトを作ります。「色情報」種類のはじめの手順には、引数に元となる色情報や色の名前を指定できます。

折れ線グラフのサンプル

「折れ線グラフ図形」種類を使ったサンプルプログラムを作ってみました。

// 折れ線グラフ図形.rdr (「折れ線グラフ図形」種類定義を除く)

メイン画面を表示する
待機する

メイン画面とは
	ウィンドウを継承する
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
		描画する
	終わり
	初期化する手順
	ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
	この設計スケール比率を{144,144}に変える
	この実質大きさを{400,300}に変える
	この内容を「キャンバス画面」に変える
	初期化開始する
	キャンバス1というキャンバスを作る
		その位置と大きさを{0,0,400,300}に変える
		その倍率を1.5に変える
		そのドッキング方向を「全体」に変える
	初期化終了する
終わり
	描画する手順
		折れ線グラフ図形(キャンバス1)を作ってグラフとする
			その位置と大きさを{0,0,400,300}に変える
			その線色は、オレンジ
		グラフのグラフ値リスト={
			0,60,10,16,36,50,80,0
		}
		グラフのサンプル数=10
		グラフをキャンバス1に追加する
		キャンバス1を更新する
	終わり

	開いた時の手順
		グラフを更新する
		キャンバス1を更新する
	終わり

	キャンバス1の大きさが変わった時の手順
		もしグラフが無なら返す
		グラフの大きさは、キャンバス1の大きさ
		グラフを更新する
		キャンバス1を更新する
	終わり
終わり

メイン画面の設計

それではガジェットのメイン画面を作っていきます。

メイン画面はグラフと計測値を表示するだけのシンプルなデザインです。そのため貼り付けるのは、キャンバス部品だけです。

キャンバスには、次の図形を作っておきます。

  • 送信量(Up)の折れ線グラフ図形
  • 受信量(Down)の折れ線グラフ図形
  • Upのキャンバス文字
  • Downのキャンバス文字

またメイン画面には、1秒ごとに値を計測するために「タイマー」を定義します。

// 通信データ量グラフ.rdr (一部, 「折れ線グラフ図形」種類定義を除く)

メイン画面を表示する
待機する

メイン画面とは
  ウィンドウを継承する
  はじめの手順
    初期化する
    ーー貼り付けた部品に対する操作をここに書きます
    タイマー1というタイマーを作る
    タイマー1の時間になった時の手順は、時間になった
    タイマー1の間隔を1000に変える
    タイマー1を開始する
    描画する
  終わり
  初期化する手順
  ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
  この実質大きさを{531,196}に変える
  この最前面を○に変える
  この種類を「ツール」に変える
  この内容を「ネットワーク通信量グラフ」に変える
  このドラッグドロップを○に変える
  初期化開始する
  キャンバス1というキャンバスを作る
    その位置と大きさを{0,0,531,196}に変える
    その倍率を1.5に変える
    その実質大きさを{531,196}に変える
    そのドッキング方向を「全体」に変える
  初期化終了する
  この設計スケール比率を{144,144}に変える
終わり

  描画する手順
    折れ線グラフ図形(キャンバス1)を作ってダウングラフとする
      その位置を{0,0}に変える
      その大きさをキャンバス1の大きさに変える
      その線色は、青
    ダウングラフをキャンバス1に追加する
    折れ線グラフ図形(キャンバス1)を作ってアップグラフとする
      その位置を{0,0}に変える
      その大きさをキャンバス1の大きさに変える
      その線色は、赤
    アップグラフをキャンバス1に追加する
    キャンバス1へ「Down」という文字を描いてダウンラベルとする
      その位置は、{10,30}
      そのフォントを「メイリオ」に変える
      その文字色を青に変える
       その文字サイズを14に変える
    キャンバス1へ「Up」という文字を描いてアップラベルとする
      その位置は、{10,10}
      そのフォントを「メイリオ」に変える
      その文字色を赤に変える
       その文字サイズを14に変える
    キャンバス1を更新する
  終わり

  開いた時の手順
    ダウングラフを更新する
    アップグラフを更新する
    キャンバス1を更新する
  終わり

  キャンバス1の大きさが変わった時の手順
    もしダウングラフが無なら返す
    ダウングラフの大きさは、キャンバス1の大きさ
    アップグラフの大きさは、キャンバス1の大きさ
    キャンバス1を更新する
  終わり
終わり

タイマーで計測してグラフに反映する

タイマーを使って、WMIで計測したネットワークの総送信量と総受信量を1秒おきに調べます。そして、1秒前に測定した値との差を計算して、その値から1秒あたりの通信量を割り出します。

なおWMIで得られる値は、バイト単位(1バイト=8ビット)ですが、今回はタスクマネージャと同じ単位であるKbpsに合わせておきます。

グラフを描くための座標の計算は、「折れ線グラフ図形」種類に任せていますので、ここでは、グラフに値を加えることと、2つのグラフで合わせた最大値を設定することだけ考えればOKです。

// 通信データ量グラフ.rdr (続き)

メイン画面とは

/* 前半は上記と同じ */

  -受信累積:長整数=0
  -送信累積:長整数=0
  時間になった手順
    WMIから「SELECT CurrentBandwidth, BytesReceivedPersec, BytesSentPersec FROM Win32_PerfRawData_Tcpip_NetworkInterface」で取得して結果リストとする
    結果リストのすべてのオブジェクトについてそれぞれ繰り返す
      オブジェクトのすべての要素についてそれぞれ繰り返す
        もし要素の名前は、「BytesReceivedPersec」なら
          測定前=受信累積
          受信累積=要素の値/1024*8  //累積KB
          もし測定前が0より大きいなら
            単位時間受信量=(受信累積-測定前)
          もし終わり
        他でもし要素の名前は、「BytesSentPersec」なら
          測定前=送信累積
          送信累積=要素の値/1024*8  //累積KB
          もし測定前が0より大きいなら
            単位時間送信量=(送信累積-測定前)
          もし終わり
        もし終わり
      繰り返し終わり
      繰り返しから抜け出す
    繰り返し終わり

    //ダウンロード
    ダウングラフに単位時間受信量を加える
    最大値1は、ダウングラフのグラフ値リストの最大値
    ダウンラベルの内容は、「Down:[単位時間受信量]Kbps Max:[最大値1]Kbps」

    //アップロード
    アップグラフに単位時間送信量を加える
    最大値2は、アップグラフのグラフ値リストの最大値
    アップラベルの内容は、「Up:[単位時間送信量]Kbps Max:[最大値2]Kbps」
    
    もし最大値1が最大値2より大きいなら
      ダウングラフの最大値は、最大値1
      アップグラフの最大値は、最大値1
    そうでなければ
      ダウングラフの最大値は、最大値2
      アップグラフの最大値は、最大値2
    もし終わり
    ダウングラフを更新する
    アップグラフを更新する
    
    キャンバス1を更新する
  終わり
終わり

動かしてみよう

以上でガジェットに必要なプログラムは、完成しました。実際に実行してみましょう。PCを操作していない状態では、あまり通信が行われないため変化がありませんが、例えばウェブページや動画サイトを開いてみると、グラフが変化することが確認できます。

まとめ

今回は、折れ線グラフ図形を自作して、ネットワーク伝送量ガジェットを作ってみました。定義した「折れ線グラフ図形」種類は、そのまま別の測定値の折れ線グラフ化にも利用できますので、例えばIoT機器から取得した温度や湿度をグラフ化する、といったことにも活用できます。

またWMIを使うとハードディスクの状態やCPU使用率など様々なシステムの状態値も測定できますので、本例を改造して、自分が気になる情報を見るためのガジェットが作れます。プログラム掲示板ではCPU使用率メーターガジェットのソースコードも公開していますので、そちらもチェックしてみてください。

ネットワーク伝送量ガジェットのソースコードのダウンロードはこちら

  • いいね (1)
  • 続編を読みたい (0)

コメントを残す