using System; using System.Collections.Generic; using System.Configuration; using System.Drawing; using System.IO; using System.Text; using System.Windows.Forms; using TwinCAT.Ads; namespace SIASUN.TwinCatLogger { public partial class MainForm : Form { public MainForm() { InitializeComponent(); this.ShowInTaskbar = true; this.WindowState = FormWindowState.Normal; } public string GetConfiguration(string key) { try { string value = System.Configuration.ConfigurationManager.AppSettings[key]; if (!string.IsNullOrEmpty(value)) return value; } catch (Exception ce) { } return ""; } private void MainForm_Load(object sender, EventArgs e) { this.Visible = false; this.notifyIcon1.Visible = true; //this.skinEngine1.SkinFile = "EmeraldColor1.ssk"; //皮肤文件.ssk runInDebug = GetConfiguration("测试模式").ToLower() == "true"; //try //{ // AutoStartTask.CreateLogonTask(!runInDebug); //} //catch (Exception ex) //{ // textNotice.Text = "创建开机自动启动任务失败:" + ex.Message; //} 单文件行数 = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["单文件行数"]); //LogonStart.CreateLogonTask(!runInDebug); timer1.Interval = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["刷新时间"]); if (LoadPointList()) timer2.Enabled = true; } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { //e.Cancel = true; // 取消关闭窗体 //HideToolStripMenuItem_Click(sender, e); if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) { e.Cancel = false; } else { e.Cancel = true; } } private void MainForm_SizeChanged(object sender, EventArgs e) { if (WindowState == FormWindowState.Minimized) { HideToolStripMenuItem_Click(sender, e); } } private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { OpenToolStripMenuItem_Click(sender, e); } } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { exitToolStripMenuItem.Enabled = false; this.Close(); exitToolStripMenuItem.Enabled = true; } private void HideToolStripMenuItem_Click(object sender, EventArgs e) { this.Hide(); } private void OpenToolStripMenuItem_Click(object sender, EventArgs e) { this.ShowInTaskbar = true; this.Show(); this.WindowState = FormWindowState.Normal; this.Activate(); } #region 数据 bool runInDebug = false; int 单文件行数 = 0; int 当前行数 = 0; struct PlcPoint { public string name; public string address; public Type type; } List pointList = new List(); List handleList = new List(); private TcAdsClient adsClient = new TcAdsClient(); private string[] plcAdress = ConfigurationManager.AppSettings["PLC地址"].Split(':'); private int startSignal = 0; private bool isRecording = false; private bool isManuel = false; private long stopWatch = 0; private string filePrefix = "Log_"; private string filePath = ""; private StreamWriter fileWriter = null; #endregion private Type GetTypeByName(string typename) { if (typename.ToUpper() == "BOOL") return typeof(bool); if (typename.ToUpper() == "BYTE") return typeof(Byte); if (typename.ToUpper() == "WORD") return typeof(UInt16); if (typename.ToUpper() == "DWORD") return typeof(UInt32); if (typename.ToUpper() == "INT") return typeof(Int16); if (typename.ToUpper() == "DINT") return typeof(Int32); if (typename.ToUpper() == "REAL") return typeof(float); if (typename.ToUpper() == "LREAL") return typeof(Double); return null; } private bool LoadPointList() { string filePath = GetConfiguration("点表文件"); pointList.Clear(); try { string line; string[] arrItem; PlcPoint plcPoint = new PlcPoint() { name = "", address = "", type = null }; // 创建一个 StreamReader 的实例来读取文件 ,using 语句也能关闭 StreamReader using (System.IO.StreamReader sr = new System.IO.StreamReader(filePath, Encoding.GetEncoding("GB2312"))) { // 从文件读取并显示行,直到文件的末尾 while ((line = sr.ReadLine()) != null) { arrItem = line.Split(','); if (arrItem.Length != 3) continue; plcPoint.name = arrItem[0].Trim(); plcPoint.address = arrItem[1].Trim(); if (plcPoint.address.Length == 0) continue; plcPoint.type = GetTypeByName(arrItem[2].Trim()); if (plcPoint.type == null) continue; pointList.Add(plcPoint); textNotice.Text = "已从" + filePath + "读取" + pointList.Count.ToString() + "条数据定义"; } } return true; } catch (Exception ex) { textNotice.Text = "读取数据点表文件(" + filePath + ")发生错误:" + ex.Message; return false; } } private void timer2_Tick(object sender, EventArgs e) { if (!adsClient.IsConnected || startSignal == 0) { BeginConnect(); } else if (isRecording) { stopWatch++; if (this.InvokeRequired) this.BeginInvoke((Action)delegate { lableTime.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", stopWatch / 3600, stopWatch / 60, stopWatch % 60); }); else lableTime.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", stopWatch / 3600, stopWatch / 60, stopWatch % 60); } else { if (lableTime.Text == "") lableTime.Text = "00:00:00"; else lableTime.Text = ""; } } private void timer1_Tick(object sender, EventArgs e) { try { if (adsClient.IsConnected) { if (isManuel) { ReadAllValues(); return; } bool isStart = (bool)adsClient.ReadAny(startSignal, typeof(bool)); if (!isRecording) { if (isStart) StartRecording(); } else { if (!isStart) StopRecording(); else ReadAllValues(); } } } catch (Exception ex) { textNotice.Text = "数据读取定时器发生错误:" + ex.Message; } } public int getHandle(string varName) { try { int handle = 0; if (varName.Contains(".")) handle = adsClient.CreateVariableHandle(varName); else handle = adsClient.CreateVariableHandle("." + varName); return handle; } catch (Exception ex) { textNotice.Text = "获取PLC变量(" + varName + ")发生错误:" + ex.Message; return 0; } } private void BeginConnect() { try { adsClient.Connect(plcAdress[0], Convert.ToInt32(plcAdress[1])); startSignal = getHandle(System.Configuration.ConfigurationManager.AppSettings["启动信号"]); if (startSignal == 0) return; for (int i = 0; i < pointList.Count; i++) { handleList.Add(getHandle(pointList[i].address)); } button1.Enabled = true; timer1.Enabled = true; } catch (Exception ex) { textNotice.Text = "连接PLC发生发生错误:" + ex.Message; timer1.Enabled = false; button1.Enabled = false; } } private void StartRecording() { if (!CreateLogFile()) return; isRecording = true; stopWatch = 0; button1.Text = "正在记录"; textNotice.Text = "已创建记录文件:" + filePath; } private void StopRecording() { fileWriter.Flush(); fileWriter.Close(); isRecording = false; button1.Text = "开始记录"; textNotice.Text = "已保存到记录文件:" + filePath; } private bool CreateLogFile() { filePath = filePrefix + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".csv"; 当前行数 = 0; try { fileWriter = new StreamWriter(filePath, false, Encoding.GetEncoding("GB2312")); fileWriter.Write("时间"); for (int i = 0; i < pointList.Count; i++) { fileWriter.Write("," + pointList[i].name); } fileWriter.WriteLine(); fileWriter.Flush(); return true; } catch (Exception ex) { textNotice.Text = "创建记录文件(" + filePath + ")发生错误:" + ex.Message; timer1.Enabled = false; button1.Enabled = false; timer2.Enabled = false; return false; } } public delegate void AsyncEventHandler(); private static object m_Lock = new object(); private string getValue(int index) { try { if (handleList[index] == 0) return ""; string value = adsClient.ReadAny(handleList[index], pointList[index].type).ToString(); return value; } catch (Exception ex) { textNotice.Text = "读取PLC变量(" + pointList[index].name + ")值时发生错误:" + ex.Message; return ""; } } private void ReadAllValues() { AsyncEventHandler asy = new AsyncEventHandler(AsyncReadAllValues); IAsyncResult result = asy.BeginInvoke(null, asy); } private void AsyncReadAllValues() { StringBuilder line = new StringBuilder(); line.Append(DateTime.Now.ToString("HH:mm:ss:fff")); for (int i = 0; i < handleList.Count; i++) { string value = getValue(i); line.Append("," + value); } lock (m_Lock) { fileWriter.WriteLine(line); 当前行数++; if (单文件行数 > 0 && 当前行数 >= 单文件行数) { fileWriter.Flush(); fileWriter.Close(); CreateLogFile(); } } } private void button1_Click(object sender, EventArgs e) { if (isRecording) { StopRecording(); isManuel = true; timer1.Enabled = false; timer2.Enabled = false; button1.Text = "已停止"; } else { if (isManuel) { isManuel = false; timer1.Enabled = true; timer2.Enabled = true; button1.Text = "开始记录"; } else { isManuel = true; StartRecording(); } } } } }