using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NationalInstruments.NI4882;	 // GPIBクラスをインポート

namespace Sample
{
    class GPIB_NI
    {
        // (0)クラス内変数
        private Device GpibDevice;                                  // GPIB Device
        public string MsgBuf = "";                                  // 受信データ

        // (1)接続
        public bool OpenInterface(string BoardID, string PrimaryAddress)
        {
            bool ret = false;

            try
            {
                GpibDevice = new Device(Convert.ToInt32(BoardID), Convert.ToByte(PrimaryAddress), 0, TimeoutValue.T1s);     // GPIBオブジェクトを作成
                ret = true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

            return ret;
        }

        // (2)切断
        public bool CloseInterface()
        {
            bool ret = false;

            try
            {
                GpibDevice.Dispose();                                                   // GPIBオブジェクトを破棄
                ret = true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

            return ret;

        }

        // (3)コマンド送信
        public bool SendMsg(string strMsg)
        {
            bool ret = false;

            try
            {
                strMsg += "\r\n";                                                       // ターミネータ「CR+LF」を付加
                GpibDevice.Write(strMsg);                                               // 送信バッファに書き込み
                ret = true;
            }
            catch (Exception e)
            {
                MsgBuf = "Error";
                MessageBox.Show(e.Message);
            }

            return ret;

        }

        // (4)受信
        public bool ReceiveMsg(long timeout_ms)
        {
            bool ret = false;
            string rcv = "";
            StringBuilder buf = new StringBuilder();
            Stopwatch sw = new Stopwatch();

            MsgBuf = "";                                                                // 受信データをクリア
            sw.Start();                                                                 // タイムアウト用ストップウォッチを開始
                                                                                        // ターミネータ「LF」を受信するまでループ 
            while (true)
            {
                try
                {
                    rcv = "";
                    rcv = GpibDevice.ReadString();                                      // 受信バッファから読み取り
                    rcv = rcv.Replace("\r", "");                                        // 受信データ内の「CR」を削除
                    if (rcv.IndexOf("\n") >= 0)                                         // ターミネータ「LF」を受信したら終了
                    {
                        rcv = rcv.Substring(0, rcv.IndexOf("\n"));                      // 受信データを「LF」の手前までで切り詰め
                        buf.Append(rcv);                                                // 受信データを保存
                        MsgBuf = buf.ToString();
                        break;
                    }
                    else
                    {
                        buf.Append(rcv);                                                // 受信データを保存
                    }
                    // タイムアウト処理
                    if (sw.ElapsedMilliseconds > timeout_ms)
                    {
                        MsgBuf = "Timeout";
                        MessageBox.Show(MsgBuf);
                        return ret;
                    }
                }
                catch (Exception e)
                {
                    GpibStatusFlags statusFlag = GpibDevice.GetCurrentStatus();
                    if ((statusFlag & GpibStatusFlags.IOComplete) == 0)
                    {
                        // IO Complete以外の例外
                        MsgBuf = "Error";
                        MessageBox.Show(e.Message);
                        return ret;
                    }
                    else
                    {
                        // IO Complete例外
                        rcv = rcv.Replace("\r", "");                                    // 受信データ内の「CR」を削除
                        if (rcv.IndexOf("\n") >= 0)                                     // ターミネータ「LF」を受信したら終了
                        {
                            rcv = rcv.Substring(0, rcv.IndexOf("\n"));                  // 受信データを「LF」の手前までで切り詰め
                            buf.Append(rcv);                                            // 受信データを保存
                            MsgBuf = buf.ToString();
                            break;
                        }
                        else
                        {
                            buf.Append(rcv);                                            // 受信データを保存
                        }
                        // タイムアウト処理
                        if (sw.ElapsedMilliseconds > timeout_ms)
                        {
                            MsgBuf = "Timeout";
                            MessageBox.Show(MsgBuf);
                            return ret;
                        }
                    }
                }
            }
            sw.Stop();                                                                  // ストップウォッチを停止
            ret = true;

            return ret;
        }

        // (5)コマンド送受信
        public bool SendQueryMsg(string strMsg, long timeout_ms)
        {
            bool ret = false;

            ret = SendMsg(strMsg);                                                      // コマンド送信
            if (ret)
            {
                if (strMsg.Contains("?"))
                {
                    ret = ReceiveMsg(timeout_ms);                                       // 送信が成功したら応答を受信
                }
            }

            return ret;
        }
    }

}
