【⑤Visual StudioとC#でサーバーサイドの実装】設備データをWebアプリでグラフ化

昨今、製造業では『スマートファクトリー』や『DX』に注目が集まっています。

その一環として、製造工程の設備データ(PLC)を一元管理して、定周期でデータベースに蓄積することがよくあります。

蓄積しただけで活用されないということがないように活用方法の一つを紹介していきます。

今回は以下で紹介している記事の手順⑤になります。

実際にMicrosoftが開発したプログラミング言語であるC#を用いて、サーバーサイドの実装をしていきます。

パッケージのインストール方法

PostgreSQLに接続するためのNpgsqlとJsonファイルを扱うNewtonsoft.Jsonをインストールしていきます

  1. ソリューションエクスプローラーのプロジェクト名を右クリックする
  2. NuGetパッケージの管理を選択する
  3. 参照タブの検索欄にNpgsqlと入力して、インストールをクリックする

4. インストール済みタブにNpgsqlがあれば正常に完了しています。

5. 同じ手順でNewtonsoft.Jsonをインストールします。

設定情報をjsonファイルで作成

PostgreSQLへの接続情報をConfig\Settings.jsonに書き出します。

{
  "POSTGRE": {
    "HOST": "localhost",
    "PORT": "5432",
    "SVC_NM": "postgres",
    "USER": "postgres",
    "PASS": "horicontent"
  }
}

モデルクラスの作成

PostgreSQLの接続情報を保持するクラスを作成

PostgreSQLの接続情報を保持するクラスをApp_Code\Libs\Setting\postgre.csに作成します。

自作モジュールはApp_Code配下に置かないとインポートできなくなるので注意が必要です。

/*DB接続設定モジュール*/
namespace Libs.Setting
{
    /// <summary>
    /// HOST:ホスト名
    /// PORT:ポート番号
    /// SVC_NM:サービス名
    /// USER:ユーザー名
    /// PASS:パスワード
    /// </summary>
    public class Postgre
    {
        public string HOST { get; set; }
        public string PORT { get; set; }
        public string SVC_NM { get; set; }
        public string USER { get; set; }
        public string PASS { get; set; }

    }
}

設定情報を読み込むクラスを作成

設定情報を読み込むクラスをApp_Code\Libs\Common\Settings.csに作成します。

/*DB接続モジュール*/
using Libs.Setting;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Libs.Common
{
    /// <summary>
    /// DB処理関係をまとめたクラス
    /// </summary>
    public static class DbConnect
    {
        /// <summary>
        /// DB接続文字列の作成
        /// </summary>
        /// <param name="settings">設定ファイル情報</param>
        /// <returns>DB接続文字列</returns>
        public static string connect(Postgre postgre)
        {
            string ConnectionString = string.Format(
                "Server={0};Port={1};Username={2};Password={3};Database={4}",
                postgre.HOST,
                postgre.PORT,
                postgre.USER,
                postgre.PASS,
                postgre.SVC_NM);
            return ConnectionString;
        }
    }
}

PostgreSQLに接続するためのクラスを作成

PosrreSQLに接続するためのクラスをApp_Code\Libs\Common\Connect.csに作成します。

/*DB接続モジュール*/
using Libs.Setting;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Libs.Common
{
    /// <summary>
    /// DB処理関係をまとめたクラス
    /// </summary>
    public static class Connect
    {
        /// <summary>
        /// DB接続文字列の作成
        /// </summary>
        /// <param name="settings">設定ファイル情報</param>
        /// <returns>DB接続文字列</returns>
        public static string DbConnect(Postgre postgre)
        {
            string ConnectionString = string.Format(
                "Persist Security Info=True;Server={0};Port={1};Username={2};Password={3};Database={4}",
                postgre.HOST,
                postgre.PORT,
                postgre.USER,
                postgre.PASS,
                postgre.SVC_NM);
            return ConnectionString;
        }

        /// <summary>
        /// カラム名一覧を取得
        /// </summary>
        /// <param name="ConnectionString">DB接続文字列</param>
        /// <returns>カラム名一覧</returns>
        public static List<string> GetColumnName(string ConnectionString)
        {
            var columnName = new List<string>();
            try
            {
                using (var conn = new NpgsqlConnection(ConnectionString))
                {
                    conn.Open();
                    using (var cmd = new NpgsqlCommand(SelectColumnNameList("facilities"), conn))
                    {
                        using (var reader = cmd.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                columnName.Add(reader.GetString(0));
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return columnName;
        }

        /// <summary>
        /// データの取得
        /// </summary>
        /// <param name="ConnectionString"></param>
        /// <param name="columnName"></param>
        /// <returns></returns>
        public static List<List<object>> GetData(string ConnectionString, string columnName)
        {
            var res = new List<List<object>>();
            try
            {
                using (var conn = new NpgsqlConnection(ConnectionString))
                {
                    conn.Open();
                    using (var cmd = new NpgsqlCommand(SelectData(columnName), conn))
                    {
                        using (var reader = cmd.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                var r = new List<object>();
                                for (int i = 0; i < reader.FieldCount; i++)
                                {
                                    r.Add(reader[i]);
                                }
                                res.Add(r);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return res;
        }

        /// <summary>
        /// カラム名一覧取得のSQL文
        /// </summary>
        /// <returns>SQL文</returns>
        public static string SelectColumnNameList(string TableName)
        {
            return string.Format("select information_schema.columns.column_name, (select description from pg_description where  pg_description.objoid=pg_stat_user_tables.relid and  pg_description.objsubid=information_schema.columns.ordinal_position ) from  pg_stat_user_tables,  information_schema.columns where pg_stat_user_tables.relname='{0}' and pg_stat_user_tables.relname=information_schema.columns.table_name", TableName);
        }

        /// <summary>
        /// データ取得のSQL文
        /// </summary>
        /// <returns>SQL文</returns>
        public static string SelectData(string columnName)
        {
            return string.Format("SELECT タイムスタンプ,{0} FROM facilities", columnName);
        }
    }
}

上記のコードを作成すると以下のエラーが発生するので、Web.configassembliesタグに追記する。

参照されていないアセンブリに定義されています。アセンブリ’

netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51

‘に参照を追加する必要があります。

参照されていないアセンブリに定義されています。アセンブリ’

System.Data.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

‘に参照を追加する必要があります。

<add assembly="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"/>
<add assembly="System.Data.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>

エントリーポイントとなるクラスを編集

メインの処理は、プロジェクト作成時に自動で作成されているDefault.aspx.csに書いていきます。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using Libs.Common;

public partial class _Default : Page
{
    /// <summary>
    /// プロパティ
    /// settings: 設定ファイル情報
    /// </summary>
    public Settings settings { get; set; }
    public string ConnectionString { get; set; }

    public _Default()
    {
        // 設定ファイルの読み込み
        this.settings = new Settings();
        settings.Load();
        this.ConnectionString = Connect.DbConnect(settings._settings.POSTGRE);
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        // 最初のアクセス時にのみ行う初期化処理
        if (IsPostBack == false)
        {
            try
            {
                // カラム名一覧の取得
                List<string> columnNameList = Connect.GetColumnName(this.ConnectionString);
                // ドロップダウンリストに追加
                foreach (var t in columnNameList)
                {
                    DropDownList1.Items.Add(t);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        try
        {
            // HTMLからカラム名を取得
            string columnName = DropDownList1.SelectedValue;
            // グラフの初期設定
            Chart1.Series.Add("series1");
            Chart1.Series["series1"].ChartType = SeriesChartType.Line;
            Chart1.Series["series1"].XValueType = ChartValueType.DateTime;
            Chart1.Series["series1"].BorderWidth = 3;
            Chart1.ChartAreas["ChartArea1"].AxisX.LabelStyle.Format = "MM/dd HH:mm";
            Chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false;
            Chart1.ChartAreas["ChartArea1"].AxisY.ScaleBreakStyle.StartFromZero = StartFromZero.Auto;
            // データの取得
            List<List<Object>> data = Connect.GetData(this.ConnectionString, columnName);
            foreach (var t in data)
            {
                // グラフにデータ挿入
                Chart1.Series["series1"].Points.AddXY((DateTime)t[0], (decimal)t[1]);
            }

        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}

デバッグモードでアプリを実行する

ソースコードの作成ができたら動作確認をしてエラーが発生したら対象の箇所を修正していきます。

IIS Express(Google Chrome)をクリックしてデバッグモードでアプリを実行します。

動作に問題が無いことを確認できたら完了です。

まとめ

いかがだったでしょうか。

これでサーバーサイドの実装が完了して、Webアプリを作成することができました。

いよいよ次はWindowsサーバーへ公開です。

【⑥ASP.NETのWebフォームをIISにデプロイ】設備データをWebアプリでグラフ化

あともう一歩です!!