123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- using OPC_Client;
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Timers;
- using System.Xml.Linq;
- namespace EBRDemo
- {
- class SCADA
- {
- private OPC_Client.Client client = new OPC_Client.Client();
- /// <summary>
- /// 第一个string代表唯一设备编码,第二个string代表批次信息
- /// </summary>
- private Dictionary<string, string> BatchNums = new Dictionary<string, string>();
- //每10s在屏幕显示一次值
- private static System.Timers.Timer timer = new System.Timers.Timer(5000);
- private string _opcServerName = "Studio.Scada.OPC.5";//现场服务器名称
- // private string _opcServerName = "Kepware.KEPServerEX.V6";//测试服务器名称
- /// <summary>
- /// 添加采集点位
- /// </summary>
- public void AddItems()
- {
- string path = @"采集点位.csv";//采集点位item,需要与实际一致
-
- DataTable table = ReadCSV(path);
- if (table.Columns.Count == 3)
- {
- foreach (DataRow row in table.Rows)
- {
- client.itemIDs.Add(row[0].ToString());
- client.descritions.Add(row[1].ToString());
- client.equipMentCodes.Add(row[2].ToString());
- }
- //建立连接
- client._opcServerName = _opcServerName;
- client.Connect();
- if (client.isConnected)
- {
- //MessageBox.Show("未连接成功");
- Console.WriteLine("连接成功");
- }
- else
- {
- Console.WriteLine("未连接成功");
- }
- //数据变化时
- client.Data_Change += Client_DataChange;
- //异步写入多个值的回调方法
- client.Async_WriteMuchComplete += AsyncWriteMuchComplete;
- timer.Elapsed += OnTimedEvent;
- timer.AutoReset = true;
- timer.Enabled = true;
- }
- }
- private void OnTimedEvent(Object source, ElapsedEventArgs e)
- {
- Console.WriteLine("每10s输出一次值");
- //WriteSingleValue("数据类型示例.8 位设备.S 寄存器.String4", "demossss");
- //WriteMuchValue();
- foreach (OPC_Client.Data data in client.dataCenter.Values)
- {
- Console.WriteLine(data.itemID + ":" + data.value.ToString());
- Console.WriteLine("数据类型" + ":" + data.dataType.ToString());
- }
- }
- /// <summary>
- /// 写入值回调方法
- /// TransactionID,人为设置规定的标识ID
- /// </summary>
- /// <param name="TransactionID"></param>
- /// <param name="NumItems"></param>
- /// <param name="ClientHandles"></param>
- /// <param name="Errors"></param>
- private void AsyncWriteMuchComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array Errors)
- {
- }
- /// <summary>
- /// NumItems 变化的数据数目
- /// ClientHandles clientID
- /// </summary>
- /// <param name="NumItems"></param>
- /// <param name="ClientHandles"></param>
- private void Client_DataChange(int NumItems, ref Array ClientHandles)
- {
- }
- #region 数据更改
- /// <summary>
- /// 刷新所有数据,不需要高频使用
- /// </summary>
- private void AsyncRefreshAll()
- {
- client.AsyncRefreshAll();
- }
- /// <summary>
- /// 更新批次号
- /// </summary>
- private void UpdateBatchNum()
- {
- foreach (Data data in client.dataCenter.Values)
- {
- string batchNum = "";
- //根据设备编码获取当前批次信息
- if (BatchNums.TryGetValue(data.equipMentCode, out batchNum))
- data.batchNum = batchNum;
- }
- }
- /// <summary>
- /// 写单个值
- /// </summary>
- private void WriteSingleValue(string item,object obj_value)
- {
- try
- {
- //根据item值,更新值
- //如果数据类型不对,可能导致错误
- client.WriteOneValue(item, obj_value);
- }
- catch(Exception err)
- {
- Console.WriteLine(err.Message);
- }
- }
- /// <summary>
- /// 写多个值
- /// </summary>
- private void WriteMuchValue()
- {
- try
- {
- List<string> itemIds = new List<string>();
- itemIds.Add("通道 1.设备 1.标记 1");
- itemIds.Add("通道 1.设备 1.标记 2");
- itemIds.Add("通道 1.设备 1.标记 3");
- itemIds.Add("数据类型示例.8 位设备.S 寄存器.String1");
- List<object> values = new List<object>();
- values.AddRange(new List<object> { 17, 18, 19, "20" });
- Array erros;
- int TransactionID = 8;
- int cancelID;
- //写入方法
- client.AsyncWriteMuchValue(itemIds.Count, itemIds, values, out erros, TransactionID, out cancelID);
- }
- catch
- {
- }
- }
- #endregion;
- #region 自定义方法,可以不看
- /// 给定文件的路径,读取文件的二进制数据,判断文件的编码类型
- /// <param name="FILE_NAME">文件路径</param>
- /// <returns>文件的编码类型</returns>
- public static System.Text.Encoding GetType(string FILE_NAME)
- {
- System.IO.FileStream fs = new System.IO.FileStream(FILE_NAME, System.IO.FileMode.Open,
- System.IO.FileAccess.Read);
- System.Text.Encoding r = GetType(fs);
- fs.Close();
- return r;
- }
- /// 通过给定的文件流,判断文件的编码类型
- /// <param name="fs">文件流</param>
- /// <returns>文件的编码类型</returns>
- public static System.Text.Encoding GetType(System.IO.FileStream fs)
- {
- byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 };
- byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 };
- byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //带BOM
- System.Text.Encoding reVal = System.Text.Encoding.Default;
- System.IO.BinaryReader r = new System.IO.BinaryReader(fs, System.Text.Encoding.Default);
- int i;
- int.TryParse(fs.Length.ToString(), out i);
- byte[] ss = r.ReadBytes(i);
- if (IsUTF8Bytes(ss) || (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF))
- {
- reVal = System.Text.Encoding.UTF8;
- }
- else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00)
- {
- reVal = System.Text.Encoding.BigEndianUnicode;
- }
- else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41)
- {
- reVal = System.Text.Encoding.Unicode;
- }
- r.Close();
- return reVal;
- }
- /// 判断是否是不带 BOM 的 UTF8 格式
- /// <param name="data"></param>
- /// <returns></returns>
- private static bool IsUTF8Bytes(byte[] data)
- {
- int charByteCounter = 1; //计算当前正分析的字符应还有的字节数
- byte curByte; //当前分析的字节.
- for (int i = 0; i < data.Length; i++)
- {
- curByte = data[i];
- if (charByteCounter == 1)
- {
- if (curByte >= 0x80)
- {
- //判断当前
- while (((curByte <<= 1) & 0x80) != 0)
- {
- charByteCounter++;
- }
- //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X
- if (charByteCounter == 1 || charByteCounter > 6)
- {
- return false;
- }
- }
- }
- else
- {
- //若是UTF-8 此时第一位必须为1
- if ((curByte & 0xC0) != 0x80)
- {
- return false;
- }
- charByteCounter--;
- }
- }
- if (charByteCounter > 1)
- {
- throw new Exception("非预期的byte格式");
- }
- return true;
- }
- //导入csv文件,区分英文引号和英文逗号
- //返回字符串中特定字符个数
- private int GetNum_String_Special(string str1, string str2)
- {
- int i = 0;
- if (str1.Contains(str2))
- {
- string str3;
- str3 = str1.Replace(str2, "");
- i = (str1.Length - str3.Length) / str2.Length;
- }
- else
- {
- i = 0;
- }
- return i;
- }
- //判断一个数是奇数还是偶数,false代表偶数,true代表奇数
- //fdf
- private bool EorO(int i)
- {
- bool b = false;
- if (i % 2 == 1)
- {
- b = true;
- }
- else
- {
- b = false;
- }
- return b;
- }
- //修正csv文件中含有特殊字符(英文逗号,英文引号)
- //读取是按行进行的
- private List<string> Amend_str(string csv)
- {
- string newStr = "";
- string[] str_old = csv.Split(',');
- List<string> str_new = new List<string>();
- bool isSplice = false;//是否需要连接后面字符串
- foreach (string str in str_old)
- {
- int i = 0;
- i = GetNum_String_Special(str, "\"");
- //为奇数代表一定含有英文逗号
- //直到获取第一个奇数
- if (!isSplice)
- {
- //从0到1的跳变,代表英文逗号分隔符的起始第一个
- if (EorO(i))
- {
- isSplice = true;//表示需要与后面的字符串进行连接
- newStr += str + @",";
- }
- //为偶数,则代表不含英文逗号,可能含有英文引号
- else
- {
- //一个引号代替两个引号
- newStr = str.Replace("\"\"", "\"");
- str_new.Add(newStr);
- newStr = string.Empty;
- }
- }
- //表示后面的均为需要进行连接的字符串,如果后面的字符串中英文引号为单,则表示连接到此为止
- else
- {
- //奇数,则代表连接到此为止
- if (EorO(i))
- {
- newStr += str;
- newStr = newStr.Replace("\"\"", "\"");
- str_new.Add(newStr);
- newStr = string.Empty;
- isSplice = false;
- }
- //为偶数,则表示不是最后一个连接项
- else
- {
- newStr += str + @",";
- }
- }
- }
- return str_new;
- }
- //读取文件,返回datatable,head代表是否读取首行标题,head不可取,必须要
- //读取标题行,否则返回table容易出错,当CSV格式首航单元格不是最多的时候,易丢失数据
- private DataTable ReadCSV(string filePath)
- {
- DataTable dt = new DataTable();
- System.Text.Encoding encoding = GetType(filePath);
- System.IO.StreamReader sr = new System.IO.StreamReader(filePath, encoding); //记录每次读取的一行记录
- string strLine = "";
- //记录每行记录中的各字段内容
- string[] aryLine = null;
- string[] tableHead = null;
- //标示列数
- int columnCount = 0;
- //标示是否是读取的第一行
- bool IsFirst = true;
- //逐行读取CSV中的数据
- while ((strLine = sr.ReadLine()) != null)
- {
- if (IsFirst)
- {
- tableHead = Amend_str(strLine).ToArray();
- IsFirst = false;
- columnCount = tableHead.Length;
- //创建列
- for (int i = 0; i < columnCount; i++)
- {
- DataColumn dc = new DataColumn(tableHead[i]);
- dt.Columns.Add(dc);
- }
- }
- else
- {
- aryLine = Amend_str(strLine).ToArray();
- DataRow dr = dt.NewRow();
- for (int j = 0; j < columnCount; j++)
- {
- dr[j] = aryLine[j];
- }
- dt.Rows.Add(dr);
- }
- }
- sr.Close();
- return dt;
- }
-
- // private object obj_GetDataTable = new object();
-
- /// <summary>
- /// 连接数据库,获取table
- /// </summary>
- /// <param name="command"></param>
- /// <param name="conn"></param>
- /// <returns></returns>
- private DataTable GetDataTable(string command, string conn)
- {
- DataTable table = new DataTable();
- //连接SQL数据库
- System.Data.SqlClient.SqlConnection sqlConnection;
- System.Data.SqlClient.SqlCommand sqlCommand;
- try
- {
- //查询数据库SQL
- sqlConnection = new System.Data.SqlClient.SqlConnection(conn);
- sqlConnection.Open();
- sqlCommand = new System.Data.SqlClient.SqlCommand(command, sqlConnection);
- System.Data.SqlClient.SqlDataAdapter sda = new System.Data.SqlClient.SqlDataAdapter();
- sda.SelectCommand = sqlCommand;
- DataSet ds = new DataSet();
- sda.Fill(ds, "cs");
- table = ds.Tables[0];
- sqlConnection.Close();
- }
- catch (Exception err)
- {
- // MessageBox.Show(err.Message);
- Console.WriteLine(DateTime.Now.ToString() + ":" + err.Message);
-
- }
- return table;
- }
- #endregion
- }
- }
|