AutoAnalysisDeviceKS.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. using Microsoft.Win32;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using System.IO;
  6. using System.Threading;
  7. using System.Windows.Forms;
  8. using System.Xml;
  9. using System.Text;
  10. using System.Net;
  11. using System.Net.Sockets;
  12. using System.Text.RegularExpressions;
  13. using Oracle.ManagedDataAccess.Client;
  14. using NPOI.SS.UserModel;
  15. using NPOI.XSSF.UserModel;
  16. namespace FileWatcher
  17. {
  18. public partial class AutoAnalysisDeviceKS : Form
  19. {
  20. DataHelper dh;
  21. /// <summary>
  22. /// 用户编号
  23. /// </summary>
  24. string iusercode;
  25. /// <summary>
  26. /// 岗位资源
  27. /// </summary>
  28. string isource;
  29. Tip tipform;
  30. Thread InitDB;
  31. StringBuilder sql = new StringBuilder();
  32. /// <summary>
  33. /// 缓存的文件
  34. /// </summary>
  35. public static string CachePath = Environment.GetEnvironmentVariable("windir").Substring(0, 1) + @":/UAS_MES/XmlAnalysor/Cache.xml";
  36. /// <summary>
  37. /// 缓存的文件夹
  38. /// </summary>
  39. public static string CachePathFolder = Environment.GetEnvironmentVariable("windir").Substring(0, 1) + @":/UAS_MES/XmlAnalysor/";
  40. /// <summary>
  41. /// 需要解析的文件名
  42. /// </summary>
  43. List<string> _FileName = new List<string>();
  44. ftpOperater ftp = new ftpOperater();
  45. public AutoAnalysisDeviceKS()
  46. {
  47. tipform = new Tip();
  48. InitializeComponent();
  49. StartPosition = FormStartPosition.CenterScreen;
  50. }
  51. public AutoAnalysisDeviceKS(string iUserName, string iSource, string iMaster)
  52. {
  53. tipform = new Tip();
  54. InitializeComponent();
  55. iusercode = iUserName;
  56. isource = iSource.ToUpper();
  57. StartPosition = FormStartPosition.CenterScreen;
  58. }
  59. string IPAddress = "";
  60. private void Form1_Load(object sender, EventArgs e)
  61. {
  62. tipform.Show();
  63. CheckForIllegalCrossThreadCalls = false;
  64. FormBorderStyle = FormBorderStyle.FixedSingle;
  65. InitDB = new Thread(ConnectDB);
  66. //添加监控事件
  67. XmlWatcher.Changed += new FileSystemEventHandler(XmlWatcher_Created);
  68. //ATEFile.Changed += new FileSystemEventHandler(XmlWatcher_Created);
  69. SetLoadingWindow stw = new SetLoadingWindow(InitDB, "正在启动程序");
  70. stw.StartPosition = FormStartPosition.CenterScreen;
  71. stw.ShowDialog();
  72. List<string> CacheInf = new List<string>();
  73. IPHostEntry IpEntry = Dns.GetHostEntry(Dns.GetHostName());
  74. for (int i = 0; i < IpEntry.AddressList.Length; i++)
  75. {
  76. if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
  77. IPAddress = IpEntry.AddressList[i].ToString();
  78. }
  79. //获取缓存信息
  80. try
  81. {
  82. FolderPath.Text = BaseUtil.GetCacheData("FolderPath").ToString();
  83. Device.Text = BaseUtil.GetCacheData("Device").ToString();
  84. }
  85. catch (Exception ex) { MessageBox.Show(ex.Message); }
  86. //获取岗位资源相关信息
  87. StartWatch.PerformClick();
  88. }
  89. private void ConnectDB()
  90. {
  91. DataHelper.DBConnectionString = "Connection Timeout=0;Pooling=false;Password=select!#%*(;User ID=N_MES;Pooling=false;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.3.7)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
  92. dh = new DataHelper();
  93. }
  94. private void StartWatch_Click(object sender, EventArgs e)
  95. {
  96. if (FolderPath.Text == "")
  97. {
  98. OperateResult.AppendText("请选择监控文件夹\n");
  99. return;
  100. }
  101. else
  102. {
  103. if (!Directory.Exists(FolderPath.Text))
  104. {
  105. OperateResult.AppendText("监控文件夹不存在\n");
  106. return;
  107. }
  108. }
  109. XmlWatcher.Path = FolderPath.Text;
  110. XmlWatcher.EnableRaisingEvents = true;
  111. XmlWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
  112. //设置缓存数据
  113. BaseUtil.SetCacheData("FolderPath", FolderPath.Text);
  114. BaseUtil.SetCacheData("Device", Device.Text);
  115. Timer.Interval = 1000 * 5;
  116. Timer.Start();
  117. //设置按钮不可点击
  118. StartWatch.Enabled = false;
  119. ChooseFolder.Enabled = false;
  120. StopWatch.Enabled = true;
  121. OperateResult.AppendText("开始执行监控\n");
  122. }
  123. private void XmlWatcher_Created(object sender, FileSystemEventArgs e)
  124. {
  125. OperateResult.AppendText("文件修改:" + e.FullPath + "\n");
  126. TxtHandleProcess(e.FullPath);
  127. }
  128. string nextLine;
  129. private void TxtHandleProcess(string FileName)
  130. {
  131. }
  132. private void StopWatch_Click(object sender, EventArgs e)
  133. {
  134. XmlWatcher.EnableRaisingEvents = false;
  135. StartWatch.Enabled = true;
  136. ChooseFolder.Enabled = true;
  137. StopWatch.Enabled = false;
  138. OperateResult.AppendText("停止执行监控\n");
  139. }
  140. private void Clean_Click(object sender, EventArgs e)
  141. {
  142. OperateResult.Clear();
  143. }
  144. private void ChooseFolder_Click(object sender, EventArgs e)
  145. {
  146. FolderBrowserDialog folder = new FolderBrowserDialog();
  147. folder.Description = "选择监控文件夹";
  148. DialogResult result = folder.ShowDialog();
  149. if (result == DialogResult.OK)
  150. {
  151. FolderPath.Text = folder.SelectedPath;
  152. }
  153. }
  154. private void ChooseBackUpFolder_Click(object sender, EventArgs e)
  155. {
  156. FolderBrowserDialog folder = new FolderBrowserDialog();
  157. folder.Description = "选择备份文件夹";
  158. DialogResult result = folder.ShowDialog();
  159. if (result == DialogResult.OK)
  160. {
  161. }
  162. }
  163. private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  164. {
  165. string ExitConfirm = MessageBox.Show(this, "确认退出?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question).ToString();
  166. if (ExitConfirm != "Yes")
  167. {
  168. WindowState = FormWindowState.Minimized;
  169. e.Cancel = true;
  170. }
  171. }
  172. private void AutoStart_CheckedChanged(object sender, EventArgs e)
  173. {
  174. SetAutoRun();
  175. }
  176. private void SetAutoRun()
  177. {
  178. if (AutoStart.Checked) //设置开机自启动
  179. {
  180. string path = Application.ExecutablePath;
  181. RegistryKey rk = Registry.LocalMachine;
  182. RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
  183. rk2.SetValue("FileWatcher.exe", path);
  184. rk2.Close();
  185. rk.Close();
  186. }
  187. else //取消开机自启动
  188. {
  189. string path = Application.ExecutablePath;
  190. RegistryKey rk = Registry.LocalMachine;
  191. RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
  192. rk2.DeleteValue("FileWatcher.exe", false);
  193. rk2.Close();
  194. rk.Close();
  195. }
  196. }
  197. private void Timer_Tick(object sender, EventArgs e)
  198. {
  199. string filePath = FolderPath.Text + @"\LotLog.csv";
  200. // 插入Oracle数据库
  201. List<string[]> csvData = ReadAndFilterCsvFile(filePath);
  202. // 2. 解析数据并写入Oracle数据库
  203. WriteToOracleDatabase(csvData);
  204. }
  205. static List<string[]> ReadAndFilterCsvFile(string filePath)
  206. {
  207. var filteredData = new List<string[]>();
  208. DateTime currentTime = DateTime.Now;
  209. DateTime fiveMinutesAgo = currentTime.AddMinutes(-1440);
  210. // 使用StreamReader自动检测编码
  211. using (var reader = new StreamReader(filePath, Encoding.Default, true))
  212. {
  213. Console.WriteLine($"检测到文件编码: {reader.CurrentEncoding.EncodingName}");
  214. // 跳过第一行(版本信息行)
  215. reader.ReadLine();
  216. // 读取标题行
  217. string headerLine = reader.ReadLine();
  218. if (headerLine == null)
  219. {
  220. throw new Exception("CSV文件格式不正确,缺少标题行");
  221. }
  222. // 确定生产开始时间的列索引
  223. string[] headers = headerLine.Split(',');
  224. int startTimeIndex = Array.IndexOf(headers, "生产开始时间");
  225. if (startTimeIndex == -1)
  226. {
  227. throw new Exception("CSV文件中找不到'生产开始时间'列");
  228. }
  229. // 读取并过滤数据行
  230. while (!reader.EndOfStream)
  231. {
  232. string line = reader.ReadLine();
  233. if (!string.IsNullOrWhiteSpace(line))
  234. {
  235. string[] values = line.Split(',');
  236. // 解析生产开始时间
  237. if (startTimeIndex < values.Length &&
  238. DateTime.TryParse(values[startTimeIndex], out DateTime startTime))
  239. {
  240. // 只保留生产开始时间在当前时间5分钟以内的记录
  241. filteredData.Add(values);
  242. }
  243. }
  244. }
  245. }
  246. return filteredData;
  247. }
  248. public static Encoding DetectFileEncoding(string filePath)
  249. {
  250. // 读取文件前几个字节来检测编码
  251. byte[] buffer = new byte[5];
  252. using (FileStream file = new FileStream(filePath, FileMode.Open))
  253. {
  254. file.Read(buffer, 0, 5);
  255. file.Close();
  256. }
  257. // 检测UTF-8 with BOM
  258. if (buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF)
  259. return Encoding.UTF8;
  260. // 检测UTF-16 (Big Endian)
  261. if (buffer[0] == 0xFE && buffer[1] == 0xFF)
  262. return Encoding.BigEndianUnicode;
  263. // 检测UTF-16 (Little Endian)
  264. if (buffer[0] == 0xFF && buffer[1] == 0xFE)
  265. return Encoding.Unicode;
  266. // 默认使用GB2312(中文常用编码)
  267. return Encoding.GetEncoding("GB2312");
  268. }
  269. void WriteToOracleDatabase(List<string[]> csvData)
  270. {
  271. // Oracle连接字符串 - 根据实际情况修改
  272. string connectionString = "Connection Timeout=0;Pooling=false;Password=select!#%*(;User ID=N_MES;Pooling=false;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.3.7)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));";
  273. // 字段索引映射(根据CSV标题行顺序调整)
  274. const int BOARD_NAME_INDEX = 1; // 基板名
  275. const int START_TIME_INDEX = 4; // 生产开始时间
  276. const int END_TIME_INDEX = 6; // 生产完成时间
  277. const int ERROR_STOP_TIME_INDEX = 45; // 出错停止时间(秒)
  278. const int ERROR_REPAIR_TIME_INDEX = 46; // 出错修复时间(秒)
  279. const int COMPLETED_PANELS_INDEX = 48; // 完成贴装的拼板数
  280. const int UPSTREAM_WAIT_INDEX = 49; // 因上游待机的时间(秒)
  281. const int DOWNSTREAM_WAIT_INDEX = 50; // 因下游待机的时间(秒)
  282. const int EFFICIENCY_INDEX = 51; // 可动率(%)
  283. const int PLACEMENT_POINTS_INDEX = 52; // 贴装点数
  284. const int COMPONENT_CONSUMP_INDEX = 53; // 元件消耗数
  285. const int CONVEYOR_INDEX = 54; // 输送台
  286. using (OracleConnection connection = new OracleConnection(connectionString))
  287. {
  288. try
  289. {
  290. connection.Open();
  291. // 使用参数化SQL防止注入
  292. string insertSql = @"
  293. INSERT INTO productsmtlocation_1 (psl_id,
  294. psl_program, psl_begintime, psl_endtime, psl_stop,
  295. psl_repair, psl_boards, psl_waitupper,
  296. psl_waitlower, psl_move, psl_points,
  297. psl_consumes, psl_plat
  298. ) VALUES (productsmtlocation_seq.nextval,
  299. :boardName, :startTime, :endTime, :errorStopTime,
  300. :errorRepairTime, :completedPanels, :upstreamWaitTime,
  301. :downstreamWaitTime, :efficiency, :placementPoints,
  302. :componentConsumption, :conveyor
  303. )";
  304. using (OracleCommand command = new OracleCommand(insertSql, connection))
  305. {
  306. // 添加参数
  307. command.Parameters.Add(":boardName", OracleDbType.Varchar2);
  308. command.Parameters.Add(":startTime", OracleDbType.TimeStamp);
  309. command.Parameters.Add(":endTime", OracleDbType.TimeStamp);
  310. command.Parameters.Add(":errorStopTime", OracleDbType.Double);
  311. command.Parameters.Add(":errorRepairTime", OracleDbType.Double);
  312. command.Parameters.Add(":completedPanels", OracleDbType.Int32);
  313. command.Parameters.Add(":upstreamWaitTime", OracleDbType.Double);
  314. command.Parameters.Add(":downstreamWaitTime", OracleDbType.Double);
  315. command.Parameters.Add(":efficiency", OracleDbType.Double);
  316. command.Parameters.Add(":placementPoints", OracleDbType.Int32);
  317. command.Parameters.Add(":componentConsumption", OracleDbType.Int32);
  318. command.Parameters.Add(":conveyor", OracleDbType.Varchar2);
  319. // 遍历CSV数据行
  320. for (int i = 0; i < csvData.Count; i++)
  321. {
  322. string[] values = csvData[i];
  323. try
  324. {
  325. // 设置参数值
  326. command.Parameters[":boardName"].Value = GetStringValue(values, BOARD_NAME_INDEX);
  327. command.Parameters[":startTime"].Value = GetDateTimeValue(values, START_TIME_INDEX);
  328. command.Parameters[":endTime"].Value = GetDateTimeValue(values, END_TIME_INDEX);
  329. command.Parameters[":errorStopTime"].Value = GetDoubleValue(values, ERROR_STOP_TIME_INDEX);
  330. command.Parameters[":errorRepairTime"].Value = GetDoubleValue(values, ERROR_REPAIR_TIME_INDEX);
  331. command.Parameters[":completedPanels"].Value = GetIntValue(values, COMPLETED_PANELS_INDEX);
  332. command.Parameters[":upstreamWaitTime"].Value = GetDoubleValue(values, UPSTREAM_WAIT_INDEX);
  333. command.Parameters[":downstreamWaitTime"].Value = GetDoubleValue(values, DOWNSTREAM_WAIT_INDEX);
  334. command.Parameters[":efficiency"].Value = GetDoubleValue(values, EFFICIENCY_INDEX);
  335. command.Parameters[":placementPoints"].Value = GetIntValue(values, PLACEMENT_POINTS_INDEX);
  336. command.Parameters[":componentConsumption"].Value = GetIntValue(values, COMPONENT_CONSUMP_INDEX);
  337. command.Parameters[":conveyor"].Value = GetStringValue(values, CONVEYOR_INDEX);
  338. if (!dh.CheckExist("productsmtlocation_1",
  339. "to_char(PSL_BEGINTIME,'yyyy-mm-dd hh24:mi:ss')='"+ GetDateTimeValue(values, START_TIME_INDEX).ToString("yyyy-MM-dd HH:mm:ss") + "' " +
  340. "and psl_plat='"+ GetStringValue(values, CONVEYOR_INDEX) + "'"))
  341. {
  342. int rowsAffected = command.ExecuteNonQuery();
  343. OperateResult.AppendText($"已插入记录 {i + 1}/{csvData.Count}: {GetStringValue(values, BOARD_NAME_INDEX)}\n");
  344. }
  345. // 执行插入
  346. }
  347. catch (Exception ex)
  348. {
  349. Console.WriteLine($"插入记录 {i + 1} 失败: {ex.Message}");
  350. }
  351. }
  352. }
  353. }
  354. catch (Exception ex)
  355. {
  356. Console.WriteLine($"数据库错误: {ex.Message}");
  357. }
  358. }
  359. }
  360. static double? GetDoubleValue(string[] values, int index)
  361. {
  362. if (values == null || index >= values.Length || string.IsNullOrWhiteSpace(values[index]))
  363. return null;
  364. double result;
  365. return double.TryParse(values[index], out result) ? result : (double?)null;
  366. }
  367. static int? GetIntValue(string[] values, int index)
  368. {
  369. if (values == null || index >= values.Length || string.IsNullOrWhiteSpace(values[index]))
  370. return null;
  371. int result;
  372. return int.TryParse(values[index], out result) ? result : (int?)null;
  373. }
  374. static string GetStringValue(string[] values, int index)
  375. {
  376. return (values != null && index < values.Length) ? values[index] : null;
  377. }
  378. static DateTime GetDateTimeValue(string[] values, int index)
  379. {
  380. DateTime result;
  381. DateTime.TryParse(values[index], out result);
  382. return result;
  383. }
  384. }
  385. }