Simple OPC DA server on C#, Windows 10 pro x64

After installation clean windows 10 pro x64, download OPCGate_Demo1_21.05.2014.zip, OPCGate_OPCCoreRedist105_1_21.05.2014.zip from OPCGate and .NET Framework 3.5. Install .NET Framework 3.5 and OPC Core Components. After that run demo.cmd

If you seeĀ popup messages from windows firewall, press button “Allow access”.

Now you can test OPC server, for example checked discrete tag at “OPCGate test.exe” and look how tag changing value at “OPCView.exe”. If all work fine, you can do next step.

For simple c# project, we disable SSL and creat only one discrete tag.

Open “OPCGate.cfg” file and disable SSL value

Open “OPCGate.tag”, delete all after first line and save.

Launche Visual Studio and create new Windows Forms App. Adding 1 Button and 1 CheckBox on form. Create new class (Model.cs)

 public class Model
    {
        public string value = "0";
        public bool flag = true;
        private static TcpListener listener;
        
        public static TcpListener Listener
        {
            get { return listener; }
            set { listener = value; }
        }
        
        List<object[]> tagList = new List<object[]>();
        
        public void RunOPC()
        {
            tagList = new List<object[]>();
            tagList.Add(new object[] { "TAG 1 Discrete\\Tag1 b r" });

            if (tagList.Count > 0)
            {
                OpcExchange opc = new OpcExchange(tagList, this);
                Task runOPC = Task.Factory.StartNew(() =>
                {
                    opc.StartExchange();
                });
            }
        }
        
    }

And class “OpcExchange.cs”

class OpcExchange
    {
        Model model;
        private List<object[]> _tagList;

        public OpcExchange(List<object[]> tagList, Model model)
        {
            this.model = model;
            _tagList = tagList;
        }
        
        public void StartExchange()
        {
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint Addr = new IPEndPoint(IPAddress.Any, 43211);
            s.Bind(Addr);
            s.Listen(1); 

            Socket socket = s.Accept(); //wait connection
            byte[] rec = new byte[64];

            string hashString = "";

            while (true)
            {
                socket.Receive(rec);
                string request = Encoding.ASCII.GetString(rec);
                request = request.Substring(0, request.IndexOf("\r"));
                byte[] answer;

                switch (request)
                {
                    case "HASH":
                        hashString = "1 Discrete.Tag1 b r" + Environment.NewLine;
                        answer = Encoding.ASCII.GetBytes("HASH " + getHashSha256(hashString) + "\r\n");
                        socket.SendTo(answer, SocketFlags.None, Addr);
                        break;
                    case "SUBSCRIBE":
                        answer = Encoding.ASCII.GetBytes("SUBSCRIBE_ACK" + "\r\n");
                        socket.SendTo(answer, SocketFlags.None, Addr);
                        break;
                    case "VALUES":
                    case "PING":
                        if (model.flag)
                        {
                            answer = Encoding.ASCII.GetBytes("VALUES " + _tagList.Count + "\r\n");
                            socket.SendTo(answer, SocketFlags.None, Addr);
                            for (int i = 0; i < _tagList.Count; i++)
                            {
                                var v = "VALUE 1 " + model.value + " g " +
                                        DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + "\r\n";
                                answer = Encoding.ASCII.GetBytes(v);
                                socket.SendTo(answer, SocketFlags.None, Addr);

                            }
                            answer = Encoding.ASCII.GetBytes("");
                            model.flag = false;
                        }
                        break;
                    default:
                        if (request.Length > 7)
                        {
                            if (request.Substring(0, 10) == "PAR_CONNTO")
                            {
                                answer = Encoding.ASCII.GetBytes("PAR_CONNTO_ACK" + "\r\n");
                                socket.SendTo(answer, SocketFlags.None, Addr);
                            }
                            else
                            {
                                if (request.Substring(0, 10) == "PAR_SUBSTO")
                                {
                                    answer = Encoding.ASCII.GetBytes("PAR_SUBSTO_ACK" + "\r\n");
                                    socket.SendTo(answer, SocketFlags.None, Addr);
                                }
                            }
                        }
                        break;
                }
            }
        }
        

        public static string getHashSha256(string text)
        {
            byte[] bytes = Encoding.ASCII.GetBytes(text);
            SHA256Managed hashstring = new SHA256Managed();
            byte[] hash = hashstring.ComputeHash(bytes);
            string hashString = string.Empty;
            foreach (byte x in hash)
            {
                hashString += String.Format("{0:x2}", x);
            }
            return hashString;
        }
    }

Create buttonclick event for Button and checkedChanged event for CheckBox on your main form. All source form code:

public partial class Form1 : Form
    {
        Model model;

        public Form1()
        {
            InitializeComponent();
            model = new Model();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            model.RunOPC();
            ((Button)sender).Enabled = false;
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox chb = (CheckBox)sender;
            model.value = chb.Checked ? "1" : "0";
            model.flag = true;
        }
    }

After compile you can use this application with OPCGate. First launche OPCView.exe, select “OPC.OPCGate.demo1” in ComboBox and press “Start” button, OPC Gate start automaticly. Now start your C# application, press button and play with checkbox, you can see how value change for Discrete Tag1.

Categories: C#

2 Comments

Leave a Comment