using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

 

using TMWCommonSCL;

using TMWDnpSCL;

 

namespace DNPmasterGUI

{

  public partial class MasterForm : Form

  {

    private const int WM_VSCROLL = 0x115;

    private const int SB_BOTTOM = 7;

    private int _OldEventMask = 0;

    private const int WM_SETREDRAW = 0x000B;

    private const int EM_SETEVENTMASK = 0x0431;

 

    [DllImport("user32", CharSet = CharSet.Auto)]

    private static extern int SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);

 

    static TMWApplication pAppl;

 

    private ProtocolBuffer protocolBuffer;

    private MDNPSimDatabase db;

    private MDNPSession masterSesn;

    private DNPChannel masterChan;

    private bool pauseAnalyzer;

 

    // Timer values

    private decimal integrityPollInterval;

    private decimal integrityPollCount;

    private decimal eventPollInterval;

    private decimal eventPollCount;

 

    public MasterForm()

    {

      TMWApplicationBuilder applBuilder = new TMWApplicationBuilder();

      pAppl = applBuilder.getAppl();

      pAppl.InitEventProcessor();

      pAppl.EnableEventProcessor = true;

      pAppl.setSclLicenseKey("trial");

 

      protocolBuffer = applBuilder.getProtocolBuffer();

      protocolBuffer.ProtocolDataReadyEvent += new ProtocolBuffer.ProtocolDataReadyEventDelegate(ProtocolEvent);

      protocolBuffer.EnableCheckForDataTimer = true;

 

      InitializeComponent();

 

      masterChan = new DNPChannel();

 

      masterChan.Type = WINIO_TYPE.TCP;

      masterChan.ChnlName = ".NET DNP Master";  /* name displayed in analyzer window */

      masterChan.WinTCPipAddress = "127.0.0.1";

      masterChan.WinTCPipPort = 20020;

      masterChan.WinTCPmode = TCP_MODE.CLIENT;

      masterChan.OpenChannel();

 

      masterSesn = new MDNPSession(masterChan);

      masterSesn.AuthenticationEnabled = true;

      masterSesn.AuthUpdateKey = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };

 

      masterSesn.OpenSession();

 

      db = (MDNPSimDatabase)masterSesn.SimDatabase;

      // Register to receive notification of database changes

      db.UpdateDBEvent += new TMWSimDataBase.UpdateDBEventDelegate(UpdateDBEvent);

 

      customizeDatabase();

 

      // Set up integrity poll timer

      integrityPollCount = 0;

      integrityPollInterval = 3600;  // Once per hour

      IntegrityProgressBar.Value = 0;

      IntegrityProgressBar.Maximum = (int)integrityPollInterval;

      IntegrityPollTimer.Start();

 

      // Set up event poll timer

      eventPollCount = 0;

      eventPollInterval = 5;

      EventProgressBar.Value = 0;

      EventProgressBar.Maximum = (int)eventPollInterval;

      EventPollTimer.Start();

    }

 

    private delegate void UpdatePointDelegate(TMWSimPoint simPoint);

 

    private void customizeDatabase()

    {

      ushort i;

 

      db.Clear();

 

      /* Add 3 of each of the following types:

       *  Binary Input

       *    Value = False, Flags = onLine, class = 1

       *  Binary Output

       *    Value = False, Flags = onLine, class = 3, ControlMask = 0x3ff (allow all control operations)

       *  Analog Input

       *    Value = 0, Flags = 0, classMask = 2, Deadband = 5

       *  Analog Output

       *    Value = 0, Flags = onLine; classMask = 3

       *  Binary Counter

       *    Value = 0, Flags = onLIne, classMask = 2, frozenClassMask = 2

       */

      for (i = 0; i < 3; i++)

      {

        db.AddBinIn(i);

        db.AddBinOut(i);

        db.AddAnlgIn(i);

        db.AddAnlgOut(i);

        db.AddBinCntr(i);

      }

 

      /* Don't add any of the following data types:

       *   Double Bit Input

       *   String

       *   Vterm

       */

    }

 

    private void ScrollToBottom()

    {

      SendMessage(new HandleRef(protocolAnalyzer, Handle), WM_VSCROLL, SB_BOTTOM, 0);

    }

 

    private void BeginUpdate()

    {

      // Prevent the control from raising any events

      _OldEventMask = SendMessage(new HandleRef(protocolAnalyzer, Handle), EM_SETEVENTMASK, 0, 0);

 

      // Prevent the control from redrawing itself

      SendMessage(new HandleRef(protocolAnalyzer, Handle), WM_SETREDRAW, 0, 0);

    }

 

    private void EndUpdate()

    {

      // Allow the control to redraw itself

      SendMessage(new HandleRef(protocolAnalyzer, Handle), WM_SETREDRAW, 1, 0);

 

      // Allow the control to raise event messages

      SendMessage(new HandleRef(protocolAnalyzer, Handle), EM_SETEVENTMASK, 0, _OldEventMask);

    }

 

    private void RemoveTopLines(int numLines)

    {

      int lastLine = protocolAnalyzer.Lines.GetLength(0) - 1;

      if (numLines < 1)

      {

        return;

      }

      else if (numLines > lastLine)

      {

        numLines = lastLine;

      }

 

      int startChar = protocolAnalyzer.GetFirstCharIndexFromLine(0);

      int endChar = protocolAnalyzer.GetFirstCharIndexFromLine(numLines);

 

      bool b = protocolAnalyzer.ReadOnly;

      protocolAnalyzer.ReadOnly = false;

      protocolAnalyzer.Select(startChar, endChar - startChar);

      protocolAnalyzer.SelectedRtf = "";

      protocolAnalyzer.ReadOnly = b;

    }

 

    private void ProtocolEvent(ProtocolBuffer buf)

    {

      if (!pauseAnalyzer)

      {

        for (int i = buf.LastProvidedIndex; i < buf.LastAddedIndex; i++)

        {

          protocolAnalyzer.AppendText(protocolBuffer.getPdoAtIndex(i).ProtocolText);

          SendMessage(new HandleRef(protocolAnalyzer, protocolAnalyzer.Handle), WM_VSCROLL, SB_BOTTOM, 0);

        }

 

        // remove lines from the text box

        if (protocolAnalyzer.Lines.Length > 1000)

        {

          BeginUpdate();

          RemoveTopLines(100);

          ScrollToBottom();

          EndUpdate();

        }

      }

    }

 

    private void updateBinaryInput(TMWSimPoint simPoint)

    {

      string strVal = (simPoint as MDNPSimBinIn).Value ? "On" : "Off";

      Color textColor = (simPoint as MDNPSimBinIn).Value ? Color.ForestGreen : Color.Red;

 

      switch (simPoint.PointNumber)

      {

        case 0:

          BinIn0.Text = strVal;

          BinIn0.ForeColor = textColor;

          break;

        case 1:

          BinIn1.Text = strVal;

          BinIn1.ForeColor = textColor;

          break;

        case 2:

          BinIn2.Text = strVal;

          BinIn2.ForeColor = textColor;

          break;

        default:

          protocolBuffer.Insert("Received update for unexpected binary input point: " + simPoint.PointNumber.ToString());

          break;

      }

    }

 

    private void updateBinaryOutput(TMWSimPoint simPoint)

    {

      string strVal = (simPoint as MDNPSimBinOut).Value ? "On" : "Off";

      Color textColor = (simPoint as MDNPSimBinOut).Value ? Color.ForestGreen : Color.Red;

 

      switch (simPoint.PointNumber)

      {

        case 0:

          BinOut0Feedback.Text = strVal;

          BinOut0Feedback.ForeColor = textColor;

          break;

        case 1:

          BinOut1Feedback.Text = strVal;

          BinOut1Feedback.ForeColor = textColor;

          break;

        case 2:

          BinOut2Feedback.Text = strVal;

          BinOut2Feedback.ForeColor = textColor;

          break;

        default:

          protocolBuffer.Insert("Received update for unexpected binary output point: " + simPoint.PointNumber.ToString());

          break;

      }

    }

 

    private void updateBinCntr(TMWSimPoint simPoint)

    {

      switch (simPoint.PointNumber)

      {

        case 0:

          BinCntr0.Text = (simPoint as MDNPSimBinCntr).Value.ToString();

          break;

        case 1:

          BinCntr1.Text = (simPoint as MDNPSimBinCntr).Value.ToString();

          break;

        case 2:

          BinCntr2.Text = (simPoint as MDNPSimBinCntr).Value.ToString();

          break;

        default:

          protocolBuffer.Insert("Received update for unexpected analog input point: " + simPoint.PointNumber.ToString());

          break;

      }

    }

 

    private void updateAnalogInput(TMWSimPoint simPoint)

    {

      switch (simPoint.PointNumber)

      {

        case 0:

          AnlgIn0.Text = (simPoint as MDNPSimAnlgIn).Value.ToString();

          break;

        case 1:

          AnlgIn1.Text = (simPoint as MDNPSimAnlgIn).Value.ToString();

          break;

        case 2:

          AnlgIn2.Text = (simPoint as MDNPSimAnlgIn).Value.ToString();

          break;

        default:

          protocolBuffer.Insert("Received update for unexpected analog input point: " + simPoint.PointNumber.ToString());

          break;

      }

    }

 

    private void updateAnalogOutput(TMWSimPoint simPoint)

    {

      switch (simPoint.PointNumber)

      {

        case 0:

          AnlgOut0Feedback.Text = (simPoint as MDNPSimAnlgOut).Value.ToString();

          break;

        case 1:

          AnlgOut1Feedback.Text = (simPoint as MDNPSimAnlgOut).Value.ToString();

          break;

        case 2: