MainTps.cs 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.ComponentModel;
  7. using Tps_LQ_Transmitter.com;
  8. using System.IO;
  9. using Tps_LQ_Transmitter.models;
  10. using System.Data;
  11. using AppLibs.Devices;
  12. using System.Windows.Forms;
  13. using CommonDevHostApp.Devices;
  14. using Tps_LQ_Transmitter.Common;
  15. using System.Diagnostics;
  16. using System.Threading;
  17. namespace Tps_LQ_Transmitter
  18. {
  19. public delegate void DltShowMsg(MsgType msgType, string msg);
  20. public delegate void DltCellValueChanged(int row, int cell, bool ok, object value);
  21. public delegate void DltCellValueAdd(string series, string name,string systemch, string lower, string upper, string testval, string result);
  22. public delegate void DltRemainTime(string channel, int point, int FrequencyNumber, double CenterFreq, double testMin);
  23. public delegate void DltCurrentSeries(string series);
  24. /// <summary>
  25. /// 一个测试文件对应的测试项目
  26. /// </summary>
  27. public class MainTps
  28. {
  29. /// <summary>
  30. /// 测试人员
  31. /// </summary>
  32. public string Tester { get; set; }
  33. //测试地点
  34. public string Place { get; set; }
  35. //环境温度
  36. public string Temperature { get; set; }
  37. //当前测试的产品序列号
  38. public string Serial { get; set; }
  39. //当前测试的产品序列号所用的系统通道号(总共8路)
  40. public string SystemChofSerial { get; set; }
  41. //环境湿度
  42. public string Humidity { get; set; }
  43. //待测产品
  44. public string Product { get; set; }
  45. //测试项目
  46. public string TestProject { get; set; }
  47. //配置文件路径
  48. string FilePath;
  49. /// <summary>
  50. /// 设备节点,表示当前测试程序包含的试验设备,绑定到界面的设备列表中
  51. /// </summary>
  52. public IList<DeviceNode> Devices;
  53. /// <summary>
  54. /// 测试节点,表示当前测试程序含有的测试指标,绑定到界面的指标列表中
  55. /// </summary>
  56. public IList<TestNode> TestNodes;
  57. /// <summary>
  58. /// 手工输入表
  59. /// </summary>
  60. public DataTable ManualTable;
  61. /// <summary>
  62. /// 自动测试表
  63. /// </summary>
  64. public DataTable TestTable;
  65. /// <summary>
  66. /// 测试值字典
  67. /// </summary>
  68. public Dictionary<string,double> TestValueDict;
  69. public Dictionary<string,double> GloabConfigDict;
  70. public string DCPowerAddress;//程控电源地址
  71. public string N9030A_SA_Address;//N9030A频谱仪地址
  72. public int TestFreqSum;//频点数
  73. public TransmitterSerialPort SerialClient = new TransmitterSerialPort();
  74. public byte ThridByte;//频点控制第3个字节
  75. public byte FourthByte;//频点控制第4个字节
  76. public int ControlDelay;//控制延时
  77. public event DltCellValueChanged ManualTableCellChanged;
  78. public event DltCellValueChanged TestTableCellChanged;
  79. public event DltCellValueAdd AddTestTableCell;
  80. public event DltRemainTime RemainTimeUpdate;
  81. public event DltCurrentSeries CurrentSeries;
  82. DataTable InitTestTable,InitManualTable; //原始数据的界面,用于初始化或者重置
  83. /// <summary>
  84. /// 测试指标的结构
  85. /// </summary>
  86. List<BaseModelStruct> baseModelStructs;
  87. public MainTps()
  88. {
  89. Devices = new BindingList<DeviceNode>();
  90. TestNodes = new BindingList<TestNode>();
  91. GloabConfigDict = new Dictionary<string, double>();
  92. DCPowerAddress = "";
  93. baseModelStructs = new List<BaseModelStruct>();
  94. LoadBaseModelStructs();
  95. }
  96. #region 模板基础方法
  97. /// <summary>
  98. /// 加载配置文件
  99. /// </summary>
  100. /// <param name="filePath"></param>
  101. /// <returns></returns>
  102. public bool LoadConfigFile(string filePath)
  103. {
  104. bool ok = true;
  105. if (File.Exists(filePath) == false)
  106. {
  107. ShowMessage(MsgType.Error, string.Format("找不到配置文件:{0}", filePath));
  108. return false;
  109. }
  110. this.FilePath = filePath;
  111. using (Spire.Xls.Workbook workbook = new Spire.Xls.Workbook())
  112. {
  113. workbook.LoadFromFile(filePath);
  114. //处理Excel数据,更多请参考官方Demo
  115. Spire.Xls.Worksheet sheet = workbook.Worksheets["自动测试项总表"];
  116. if(sheet == null)
  117. {
  118. ShowMessage(MsgType.Error, "文件中找不到‘自动测试项总表’");
  119. return false;
  120. }
  121. int blankRows = 0; //避免出错
  122. int num = 0;
  123. //默认最多两百行
  124. while (num++ < 200)
  125. {
  126. //索引从1开始
  127. string col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString():"";
  128. col1 = col1.Trim();
  129. if (string.IsNullOrEmpty(col1))
  130. {
  131. blankRows++;
  132. if(blankRows > 5)
  133. {
  134. //连续5个空行以上则退出
  135. break;
  136. }
  137. }
  138. else
  139. {
  140. blankRows = 0;
  141. }
  142. if (col1.Equals("设备配置表"))
  143. {
  144. ok &= readDevices(sheet,num);
  145. //解析行数跳过,实际上还得再加上
  146. num = num + this.Devices.Count+2;
  147. }
  148. else if (col1.Equals("测试指标配置表"))
  149. {
  150. ok &= readTestNodes(workbook,sheet,num);
  151. var items = (from p in TestNodes select p.Name).Distinct().ToArray();
  152. //解析行数跳过,实际上还得再加上
  153. num = num + items.Count() + 3;
  154. }
  155. }
  156. //加载人工测试项总表
  157. sheet = workbook.Worksheets["人工测试项总表"];
  158. if (sheet != null)
  159. {
  160. blankRows = 0; //避免出错
  161. num = 0;
  162. //默认最多两百行
  163. while (num++ < 200)
  164. {
  165. //索引从1开始
  166. string col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  167. col1 = col1.Trim();
  168. if (string.IsNullOrEmpty(col1))
  169. {
  170. blankRows++;
  171. if (blankRows > 5)
  172. {
  173. //连续5个空行以上则退出
  174. break;
  175. }
  176. }
  177. else
  178. {
  179. blankRows = 0;
  180. }
  181. if (col1.Equals("人工测试项总表"))
  182. {
  183. this.ManualTable = readTable(sheet, num);
  184. if (this.ManualTable != null)
  185. {
  186. this.InitManualTable = this.ManualTable.Copy();
  187. }
  188. }
  189. }
  190. }
  191. //加载人工测试项总表
  192. sheet = workbook.Worksheets["自动测试记录表"];
  193. if (sheet != null)
  194. {
  195. blankRows = 0; //避免出错
  196. num = 0;
  197. //默认最多两百行
  198. while (num++ < 200)
  199. {
  200. //索引从1开始
  201. string col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  202. col1 = col1.Trim();
  203. if (string.IsNullOrEmpty(col1))
  204. {
  205. blankRows++;
  206. if (blankRows > 5)
  207. {
  208. //连续5个空行以上则退出
  209. break;
  210. }
  211. }
  212. else
  213. {
  214. blankRows = 0;
  215. }
  216. if (col1.Equals("自动测试记录表"))
  217. {
  218. this.TestTable = readTable(sheet, num);
  219. if(this.TestTable != null)
  220. {
  221. this.InitTestTable = this.TestTable.Copy();
  222. }
  223. }
  224. }
  225. }
  226. //加载人工测试项总表
  227. sheet = workbook.Worksheets["公共设置"];
  228. if (sheet != null)
  229. {
  230. blankRows = 0; //避免出错
  231. num = 0;
  232. //默认最多两百行
  233. while (num++ < 200)
  234. {
  235. //索引从1开始
  236. string col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  237. col1 = col1.Trim();
  238. if (string.IsNullOrEmpty(col1))
  239. {
  240. blankRows++;
  241. if (blankRows > 5)
  242. {
  243. //连续5个空行以上则退出
  244. break;
  245. }
  246. }
  247. else
  248. {
  249. blankRows = 0;
  250. }
  251. if (col1.Equals("参数表"))
  252. {
  253. //电压
  254. string WorkVolt = sheet.Range[3, 3].Value2 != null ? sheet.Range[3, 3].Value2.ToString() : "";
  255. GloabConfigDict.Add("电压", double.Parse(WorkVolt));
  256. //电流
  257. string WorkCurrent = sheet.Range[4, 3].Value2 != null ? sheet.Range[4, 3].Value2.ToString() : "";
  258. GloabConfigDict.Add("电流", double.Parse(WorkCurrent));
  259. DCPowerAddress = sheet.Range[5, 3].Value2 != null ? sheet.Range[5, 3].Value2.ToString() : "";
  260. TestFreqSum = int.Parse(sheet.Range[7, 3].Value2 != null ? sheet.Range[7, 3].Value2.ToString() : "");
  261. }
  262. }
  263. }
  264. }
  265. return ok;
  266. }
  267. /// <summary>
  268. /// 读设备配置表
  269. /// </summary>
  270. /// <param name="rowIndex">设备配置表的起始位置</param>
  271. bool readDevices(Spire.Xls.Worksheet sheet, int rowIndex)
  272. {
  273. //检查表的格式正确
  274. string col1 = sheet.Range[rowIndex + 1, 1].Value2 != null ? sheet.Range[rowIndex + 1, 1].Value2.ToString() : "";
  275. string col2 = sheet.Range[rowIndex + 1, 2].Value2 != null ? sheet.Range[rowIndex + 1, 2].Value2.ToString() : "";
  276. string col3 = sheet.Range[rowIndex + 1, 3].Value2 != null ? sheet.Range[rowIndex + 1, 3].Value2.ToString() : "";
  277. string col4 = sheet.Range[rowIndex + 1, 4].Value2 != null ? sheet.Range[rowIndex + 1, 4].Value2.ToString() : "";
  278. if (!(col1 == "设备名称" && col2 == "设备类型" && col3 == "设备型号" && col4 == "控制句柄"))
  279. {
  280. ShowMessage(MsgType.Error, "'设备配置表'行首标题位置和格式不正确");
  281. return false;
  282. }
  283. int num = rowIndex + 1;
  284. //默认最多30行
  285. while (num++ < rowIndex + 30)
  286. {
  287. col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  288. col2 = sheet.Range[num, 2].Value2 != null ? sheet.Range[num, 2].Value2.ToString() : "";
  289. col3 = sheet.Range[num, 3].Value2 != null ? sheet.Range[num, 3].Value2.ToString() : "";
  290. col4 = sheet.Range[num, 4].Value2 != null ? sheet.Range[num, 4].Value2.ToString() : "";
  291. if ( string.IsNullOrEmpty(col2) || string.IsNullOrEmpty(col3))
  292. {
  293. break;
  294. }
  295. DeviceNode dn = new DeviceNode();
  296. dn.DeviceName = col1;
  297. dn.DeviceType = col2;
  298. dn.DeviceModel = col3;
  299. dn.DeviceHandle = col4;
  300. this.Devices.Add(dn);
  301. }
  302. return true;
  303. }
  304. /// <summary>
  305. /// 读测试指标配置表
  306. /// </summary>
  307. /// <param name="rowIndex">测试指标配置表的起始位置</param>
  308. bool readTestNodes(Spire.Xls.Workbook workbook,Spire.Xls.Worksheet sheet, int rowIndex)
  309. {
  310. List<TestNode> models = new List<TestNode>();
  311. //检查表的格式正确
  312. string col1 = sheet.Range[rowIndex + 2, 1].Value2 != null ? sheet.Range[rowIndex + 2, 1].Value2.ToString() : "";
  313. string col2 = sheet.Range[rowIndex + 2, 2].Value2 != null ? sheet.Range[rowIndex + 2, 2].Value2.ToString() : "";
  314. string col3 = sheet.Range[rowIndex + 2, 3].Value2 != null ? sheet.Range[rowIndex + 2, 3].Value2.ToString() : "";
  315. string col4 = sheet.Range[rowIndex + 2, 4].Value2 != null ? sheet.Range[rowIndex + 2, 4].Value2.ToString() : "";
  316. if (!(col1 == "测试指标" && col2 == "默认勾选" && col3 == "测试模板" && col4 == "测试顺序"))
  317. {
  318. ShowMessage(MsgType.Error, "'测试指标配置表'行首标题位置和格式不正确");
  319. return false;
  320. }
  321. int num = rowIndex + 2;
  322. //默认最多100行,先解析测试指标个数
  323. while (num++ < rowIndex + 100)
  324. {
  325. col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  326. col2 = sheet.Range[num, 2].Value2 != null ? sheet.Range[num, 2].Value2.ToString() : "";
  327. col3 = sheet.Range[num, 3].Value2 != null ? sheet.Range[num, 3].Value2.ToString() : "";
  328. col4 = sheet.Range[num, 4].Value2 != null ? sheet.Range[num, 4].Value2.ToString() : "";
  329. if (string.IsNullOrEmpty(col1) || string.IsNullOrEmpty(col3))
  330. {
  331. break;
  332. }
  333. TestNode tn = new TestNode();
  334. tn.Name = col1;
  335. if(col2 == "是")
  336. {
  337. tn.IsSelected = true;
  338. }
  339. else
  340. {
  341. tn.IsSelected = false;
  342. }
  343. tn.Template = col3;
  344. int order = Int32.MaxValue;
  345. if (Int32.TryParse(col4, out order))
  346. tn.Order = order;
  347. models.Add(tn);
  348. }
  349. //再解析各通道的配置数据
  350. int colIndex = 5; //通道数据从第5列开始
  351. while(true)
  352. {
  353. col1 = sheet.Range[rowIndex + 3, colIndex].Value2 != null ? sheet.Range[rowIndex + 3, colIndex].Value2.ToString() : "";
  354. col2 = sheet.Range[rowIndex + 3, colIndex + 1].Value2 != null ? sheet.Range[rowIndex + 3, colIndex + 1].Value2.ToString() : "";
  355. //有新通道数据则继续,否则退出
  356. if(string.IsNullOrEmpty(col1) || string.IsNullOrEmpty(col2) || col2 != "启用")
  357. {
  358. break;
  359. }
  360. string channel = sheet.Range[rowIndex + 1, colIndex].Value2 != null ? sheet.Range[rowIndex + 1, colIndex].Value2.ToString() : "";
  361. //按指标个数来解析通道数据
  362. for (int i = 0; i < models.Count; i++)
  363. {
  364. col1 = sheet.Range[rowIndex + 3 + i, colIndex].Value2 != null ? sheet.Range[rowIndex + 3 + i, colIndex].Value2.ToString() : "";
  365. col2 = sheet.Range[rowIndex + 3 + i, colIndex + 1].Value2 != null ? sheet.Range[rowIndex + 3 + i, colIndex + 1].Value2.ToString() : "";
  366. if (col2 != "启用")
  367. continue;
  368. TestNode newNode = models[i].Copy();
  369. newNode.Channel = channel; //通道名
  370. newNode.ParaConfigTable = col1; //测试配置表
  371. //复制已有参数表,或者从文件解析参数表
  372. TestNode preNode = TestNodes.FirstOrDefault(x => x.ParaConfigTable == col1);
  373. if(preNode != null)
  374. {
  375. //存在则复制,避免读文件费时间
  376. newNode.Parameters = preNode.Parameters.Copy();
  377. }
  378. else
  379. {
  380. //否则找到文件中对应的配置表
  381. Spire.Xls.Worksheet paraSheet = workbook.Worksheets[col1];
  382. if (paraSheet == null)
  383. {
  384. ShowMessage(MsgType.Error, "文件中找不到参数配置表:"+ col1);
  385. continue;
  386. }
  387. //解析参数配置表
  388. newNode.Parameters = readTestParameter(paraSheet);
  389. }
  390. //如果已经创建了同名的处理对象,则直接使用,否则则新建,采用单例模式
  391. //如果注释了下面的if,就是多例模式,即同名处理模块是不同的软件对象
  392. TestNode tn = this.TestNodes.FirstOrDefault(x => x.Template == newNode.Template);
  393. if(tn != null && tn.TestModel != null)
  394. {
  395. newNode.TestModel = tn.TestModel;
  396. }
  397. else
  398. {
  399. //根据测试指标的名称,创建BaseModel指标处理对象
  400. newNode.TestModel = CreateModel(newNode.Template);
  401. }
  402. this.TestNodes.Add(newNode);
  403. }
  404. colIndex += 2; //跳过2列
  405. }
  406. return true;
  407. }
  408. BaseModel CreateModel(string template)
  409. {
  410. //如果没有这个名字的软件模块,则返回null
  411. BaseModelStruct bms = baseModelStructs.FirstOrDefault(x => x.ModelName == template);
  412. if (bms == null)
  413. {
  414. ShowMessage(MsgType.Error, "找不到名称为:" + template +" 的测试指标模块。");
  415. return null;
  416. }
  417. BaseModel model = (BaseModel)Activator.CreateInstance(bms.type);
  418. model.tps = this;
  419. model.MessageEvent += ShowMessage;
  420. return model;
  421. }
  422. void LoadBaseModelStructs()
  423. {
  424. try
  425. {
  426. Type[] types = this.GetType().Assembly.GetTypes();
  427. foreach (var item in types)
  428. {
  429. //排除接口本身
  430. if (item.Name != "BaseModel")
  431. {
  432. if (typeof(BaseModel).IsAssignableFrom(item))
  433. {
  434. BaseModel model = (BaseModel)Activator.CreateInstance(item);
  435. BaseModelStruct bms = new BaseModelStruct();
  436. bms.ModelName = model.TemplateName;
  437. bms.type = item;
  438. this.baseModelStructs.Add(bms);
  439. model = null;
  440. }
  441. }
  442. }
  443. }
  444. catch(Exception e)
  445. {
  446. ShowMessage(MsgType.Error, "实例化BaseModel测试指标模块时出现错误,某个测试指标模块创建时发生错误,请检查代码!详细错误见程序日志文件!");
  447. Bundle.log.WriteLog(AppLibs.Host.LogLevel.Error, "类:MainTps,方法:LoadBaseModelStructs", e.Message + e.StackTrace);
  448. }
  449. }
  450. /// <summary>
  451. /// 读参数配置表
  452. /// </summary>
  453. /// <returns></returns>
  454. TestParameters readTestParameter(Spire.Xls.Worksheet sheet)
  455. {
  456. TestParameters pars = new TestParameters();
  457. int blankRows = 0; //避免出错
  458. int num = 0;
  459. //默认最多两百行
  460. while (num++ < 200)
  461. {
  462. //索引从1开始
  463. string col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  464. col1 = col1.Trim();
  465. if (string.IsNullOrEmpty(col1))
  466. {
  467. blankRows++;
  468. if (blankRows > 5)
  469. {
  470. //连续5个空行以上则退出
  471. break;
  472. }
  473. }
  474. else
  475. {
  476. blankRows = 0;
  477. }
  478. if (col1.Equals("参数表"))
  479. {
  480. ///获取表中的参数
  481. List<ParameterNode> nodes = readParameters(sheet,num);
  482. foreach (var item in nodes)
  483. {
  484. if(pars.Parameters.ContainsKey(item.Name))
  485. {
  486. ShowMessage(MsgType.Error, string.Format("参数配置表:{0} 存在同名参数:{1},无法重复添加参数", sheet.Name, item.Name));
  487. continue;
  488. }
  489. pars.Parameters.Add(item.Name, item);
  490. }
  491. //解析行数跳过,实际上还得再加上
  492. num = num + nodes.Count +1;
  493. }
  494. else if (col1.Equals("测试显示表"))
  495. {
  496. //获取表中的原始显示界面
  497. pars.InitialTable = readTable( sheet, num);
  498. //解析行数跳过,实际上还得再加上
  499. num = num + pars.InitialTable.Rows.Count + 1;
  500. }
  501. }
  502. return pars;
  503. }
  504. /// <summary>
  505. /// 读参数表
  506. /// </summary>
  507. /// <param name="sheet"></param>
  508. /// <returns></returns>
  509. List<ParameterNode> readParameters(Spire.Xls.Worksheet sheet,int rowIndex)
  510. {
  511. List<ParameterNode> nodes = new List<ParameterNode>();
  512. string col1 = sheet.Range[rowIndex + 1, 1].Value2 != null ? sheet.Range[rowIndex + 1, 1].Value2.ToString() : "";
  513. string col2 = sheet.Range[rowIndex + 1, 2].Value2 != null ? sheet.Range[rowIndex + 1, 2].Value2.ToString() : "";
  514. string col3 = sheet.Range[rowIndex + 1, 3].Value2 != null ? sheet.Range[rowIndex + 1, 3].Value2.ToString() : "";
  515. string col4 = sheet.Range[rowIndex + 1, 4].Value2 != null ? sheet.Range[rowIndex + 1, 4].Value2.ToString() : "";
  516. if (!(col1 == "名称" && col2 == "类型" && col3 == "值"))
  517. {
  518. ShowMessage(MsgType.Error, "'参数表'行首标题位置和格式不正确");
  519. return nodes;
  520. }
  521. int num = rowIndex + 1;
  522. //默认最多30行
  523. while (num++ < rowIndex + 200)
  524. {
  525. col1 = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  526. col2 = sheet.Range[num, 2].Value2 != null ? sheet.Range[num, 2].Value2.ToString() : "";
  527. col3 = sheet.Range[num, 3].Value2 != null ? sheet.Range[num, 3].Value2.ToString() : "";
  528. col4 = sheet.Range[num, 4].Value2 != null ? sheet.Range[num, 4].Value2.ToString() : "";
  529. if (string.IsNullOrEmpty(col1) || string.IsNullOrEmpty(col2) || string.IsNullOrEmpty(col3))
  530. {
  531. break;
  532. }
  533. ParameterNode pn = new ParameterNode();
  534. pn.Name = col1;
  535. pn.Type = col2;
  536. pn.StrValue = col3;
  537. pn.Mark = col4;
  538. nodes.Add(pn);
  539. }
  540. return nodes;
  541. }
  542. /// <summary>
  543. /// 读表格,人工测试表和测试显示表
  544. /// </summary>
  545. /// <param name="sheet"></param>
  546. /// <returns></returns>
  547. DataTable readTable(Spire.Xls.Worksheet sheet, int rowIndex)
  548. {
  549. //先创建列,再创建行
  550. DataTable dt = new DataTable();
  551. int num = 0;
  552. while (num++ < 50)
  553. {
  554. string col = sheet.Range[rowIndex + 1, num].Value2 != null ? sheet.Range[rowIndex + 1, num].Value2.ToString() : "";
  555. if (string.IsNullOrEmpty(col))
  556. break;
  557. dt.Columns.Add(col);
  558. }
  559. //再创建行
  560. num = rowIndex + 1;
  561. //默认最多200行
  562. while (num++ < rowIndex + 200)
  563. {
  564. //首列无值就认为表格结束
  565. string val = sheet.Range[num, 1].Value2 != null ? sheet.Range[num, 1].Value2.ToString() : "";
  566. if (string.IsNullOrEmpty(val.Trim()))
  567. break;
  568. DataRow dr = dt.NewRow();
  569. dt.Rows.Add(dr);
  570. for (int i = 0; i < dt.Columns.Count; i++)
  571. {
  572. val = sheet.Range[num, i+1].Value2 != null ? sheet.Range[num, i+1].Value2.ToString() : "";
  573. dr[i] = val;
  574. }
  575. }
  576. return dt;
  577. }
  578. /// <summary>
  579. /// 检查仪器是否正常配置
  580. /// </summary>
  581. /// <returns></returns>
  582. public bool CheckDevices()
  583. {
  584. bool ok = true;
  585. AppLibs.Devices.IDeviceHost devHost = Bundle.host.GetFirstOrDefaultService<AppLibs.Devices.IDeviceHost>();
  586. foreach (DeviceNode device in this.Devices)
  587. {
  588. DeviceParameter dev = devHost.GetFirstOrDefaultDeviceID(device.DeviceHandle);
  589. if (dev == null || !(device.DeviceType == dev.DeviceType && device.DeviceModel == dev.DeviceModel))
  590. {
  591. device.State = false;
  592. ok = false;
  593. }
  594. else
  595. {
  596. device.State = true;
  597. continue;
  598. }
  599. }
  600. return ok;
  601. }
  602. public void StopClose(string[] ProductSeries,CommonVisaResource DCPower, RainwormPower rainwormPower, TransmitterSerialPort SerialClient)
  603. {
  604. if (Product.Contains("YZH16A"))//针对YZH16A的产品
  605. {
  606. SerialClient.DUT_Transmitter_Ctrol(0x00, 0x00, 0x55);//todo:掉电控制
  607. }
  608. else
  609. {
  610. SerialClient.DUT_Transmitter_Ctrol1(0x00, 0x00);//todo:掉电控制
  611. }
  612. SerialClient.SerialClose();
  613. if (ProductSeries.Length > 1)//如果测试台数大于1,则使用外部TDK电源
  614. {
  615. DCPower.Write("GLOBal:OUTPut:STATe 0\n"); DCPower.Query("*OPC?\n");//需要取消注释
  616. ShowMessage(MsgType.Info, string.Format("关闭6YYC信号源,关闭串口,关闭外部TDK电源."));
  617. }
  618. else
  619. {
  620. rainwormPower.powerOnoff(RainwormPower.State.OFF);//设置蚯蚓电源输出
  621. rainwormPower.portClose();
  622. ShowMessage(MsgType.Info, string.Format("关闭6YYC信号源,关闭串口,关闭内部蚯蚓电源."));
  623. }
  624. }
  625. /// <summary>
  626. /// 开始测试
  627. /// </summary>
  628. /// <param name="isOrderByChannel">按照指标分组还是按照通道分组</param>
  629. public void Start(bool isOrderByChannel,string[] ProductSeries, CommonVisaResource DCPower, RainwormPower rainwormPower, TransmitterSerialPort SerialClient, MatchComPara CfigComParas)
  630. {
  631. isStop = false;
  632. //清空测试数据
  633. // BaseModel.TestResults.Clear();
  634. FrmMain FrmPara = new FrmMain();
  635. byte FourthByte = 0x00;
  636. string ComPort = CfigComParas.GetComPort("1");
  637. byte ThridByte = Convert.ToByte(CfigComParas.GetThirdByte("1"), 16);
  638. int FrequencyNumber = 0;
  639. if (TestFreqSum >= CfigComParas.ComParameters.Count)//如果限定的测试频点数大于设置的频点数
  640. {
  641. FrequencyNumber = CfigComParas.ComParameters.Count;//取设置的频点数
  642. }
  643. else
  644. {
  645. FrequencyNumber = TestFreqSum;//取限定的测试频点数
  646. }
  647. int ControlDelay = this.TestNodes[0].Parameters.GetParameter<int>("控制延时");
  648. //SerialClient.SerialOpen(CfigComParas.GetComPort("1"));
  649. //ShowMessage(MsgType.Info, string.Format("打开串口."));
  650. //选择勾选项
  651. List<TestNode> nodes = this.TestNodes.Where(x => x.IsSelected == true).ToList();
  652. if (isOrderByChannel)
  653. {
  654. //按照通道分组
  655. Stopwatch TimesCounter = new Stopwatch();
  656. double testMin = 0;
  657. TimesCounter.Restart();
  658. int Channel = 1;
  659. foreach (IGrouping<string, TestNode> group in nodes.GroupBy(x => x.Channel))
  660. {
  661. if (nodes.Count == 2)
  662. {
  663. if (group.Key == nodes[0].Channel)
  664. {
  665. MessageBox.Show("将产品通道1输出电缆接【衰减】接口,产品通道2输出电缆接【陷波】接口。", "温馨提示");
  666. }
  667. else if (group.Key == nodes[1].Channel)
  668. {
  669. MessageBox.Show("将产品通道1输出电缆接【陷波】接口,产品通道2输出电缆接【衰减】接口。", "温馨提示");
  670. }
  671. }
  672. else if(nodes.Count == 1)
  673. {
  674. MessageBox.Show("将产品输出电缆接【衰减】接口。", "温馨提示");
  675. }
  676. //channel++;
  677. //排序后执行
  678. for (int point = 0; point < FrequencyNumber; point++)//频点总数
  679. {
  680. FourthByte = Convert.ToByte(CfigComParas.GetFourthByte((point + 1).ToString()), 16);
  681. double CenterFreq = double.Parse(CfigComParas.Getfreqpoint((point + 1).ToString()));
  682. for (int i = 0; i < this.TestNodes.Count; i++)
  683. {
  684. this.TestNodes[i].PointIndex = point;
  685. this.TestNodes[i].CenterFreq = CenterFreq;
  686. this.TestNodes[i].PointTotal = FrequencyNumber;
  687. }
  688. if (FrmPara.IsRuning == false)//中途点击停止测试按钮
  689. {
  690. //控制断电
  691. StopClose(ProductSeries, DCPower, rainwormPower, SerialClient);
  692. return;
  693. }
  694. //控制
  695. if (Product.Contains("YZH16A"))//针对YZH16A的产品
  696. {
  697. SerialClient.DUT_Transmitter_Ctrol(ThridByte, FourthByte, 0x55);//todo:切换频点
  698. }
  699. else
  700. {
  701. SerialClient.DUT_Transmitter_Ctrol1(ThridByte, FourthByte);//todo:切换频点
  702. }
  703. ShowMessage(MsgType.Info, string.Format("发送串口指令EB 90 {0} {1}.", ThridByte, FourthByte));
  704. testMin = TimesCounter.ElapsedMilliseconds / 1000f / 60f;
  705. Thread.Sleep(ControlDelay);//单位ms
  706. ShowMessage(MsgType.Info, string.Format("延时{0}ms.", ControlDelay));
  707. RemainTimeUpdate(group.Key, point, FrequencyNumber, CenterFreq, testMin);
  708. //Tps_LQ_Transmitter.FrmMain.BeginInvoke(new Action(() =>
  709. //{
  710. // //labRemainTime.Text = $"第{point + 1}个频点[{CenterFreq}]MHz测试,共{currFileNode.Tps.TestNodes.Count - 1}个频点,耗时{Math.Round(testMin, 2)}Min。";
  711. //}));
  712. //Tps_LQ_Transmitter.FrmMain.BeginInvoke(new FrmMain RemainTime, point, CenterFreq, testMin);
  713. // //labRemainTime.Text = $"第{point + 1}个频点[{CenterFreq}]MHz测试,共{currFileNode.Tps.TestNodes.Count - 1}个频点,耗时{Math.Round(testMin, 2)}Min。";
  714. foreach (TestNode testnode in group.OrderBy(a => a.Order))
  715. {
  716. if (FrmPara.IsRuning == false)//中途点击停止测试按钮
  717. {
  718. //控制断电
  719. StopClose(ProductSeries, DCPower, rainwormPower, SerialClient);
  720. return;
  721. }
  722. if (isStop == false)
  723. {
  724. if (nodes.Count == 1 && testnode.Name.Contains("杂波抑制"))
  725. {
  726. MessageBox.Show("将产品输出电缆接【陷波】接口。", "温馨提示");
  727. }
  728. if (nodes.Count == 2 && testnode.Name.Contains("杂波抑制"))
  729. {
  730. if (group.Key == nodes[0].Channel)
  731. {
  732. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", nodes[1].Channel, testnode.Name));
  733. }
  734. else if (group.Key == nodes[1].Channel)
  735. {
  736. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", nodes[0].Channel, testnode.Name));
  737. }
  738. }
  739. else
  740. {
  741. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", testnode.Channel, testnode.Name));
  742. }
  743. if (testnode.TestModel != null)
  744. {
  745. if (testnode.IsSelected)
  746. {
  747. currModel = testnode.TestModel;
  748. for (int i =0;i< ProductSeries.Length;i++)
  749. {
  750. if (FrmPara.IsRuning == false)//中途点击停止测试按钮
  751. {
  752. //控制断电
  753. StopClose(ProductSeries, DCPower, rainwormPower, SerialClient);
  754. return;
  755. }
  756. this.Serial = ProductSeries[i];
  757. SystemChofSerial = (Array.IndexOf(ProductSeries, ProductSeries[i]) + 1).ToString();
  758. UpDateCurrentSeries(this.Serial);
  759. // 陷波支路用于测杂波抑制,衰减支路用于测试其他指标,
  760. //双通道测试时:当测通道1的衰减支路指标时,在不换线的情况下,则进行通道2的陷波支路指标,然后换线,测通道2的衰减支路指标时,在不换线的情况下,则进行通道1的陷波支路指标。
  761. //单通道测试时,当测通道1的衰减支路指标时,换线后,单独测试通道1的陷波支路指标
  762. if (testnode.Name.Contains("杂波抑制"))
  763. {
  764. //todo:切产品同时切到陷波支路(1切8射频开关,1切2射频开关)
  765. }
  766. else
  767. {
  768. //todo:切产品同时切到衰减支路(1切8射频开关,1切2射频开关)
  769. }
  770. testnode.TestModel.Start(testnode, nodes);
  771. }
  772. }
  773. }
  774. else
  775. {
  776. ShowMessage(MsgType.Error, string.Format("测试指标:{0}/{1} 没有实例化执行模块", testnode.Channel, testnode.Name));
  777. }
  778. }
  779. else
  780. {
  781. break;
  782. }
  783. }
  784. }
  785. }
  786. }
  787. else
  788. {
  789. //按照指标名称进行
  790. foreach (IGrouping<string, TestNode> group in nodes.GroupBy(x => x.Name))
  791. {
  792. //排序后执行
  793. foreach (TestNode testnode in group.OrderBy(a => a.Order))
  794. {
  795. if (isStop == false)
  796. {
  797. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", testnode.Channel, testnode.Name));
  798. if (testnode.TestModel != null)
  799. {
  800. currModel = testnode.TestModel;
  801. // testnode.TestModel.Start(testnode);
  802. }
  803. else
  804. {
  805. ShowMessage(MsgType.Error, string.Format("测试指标:{0}/{1} 没有实例化执行模块", testnode.Channel, testnode.Name));
  806. }
  807. }
  808. else
  809. {
  810. break;
  811. }
  812. }
  813. }
  814. }
  815. //保存自动测试记录表
  816. SaveTestTable();
  817. ShowMessage(MsgType.Info, string.Format("序列号:{0} 测试完成", Serial));
  818. }
  819. bool isStop = false;
  820. BaseModel currModel = null;
  821. public void Stop()
  822. {
  823. isStop = true;
  824. if(currModel!= null)
  825. {
  826. currModel.Stop();
  827. }
  828. ShowMessage(MsgType.Info, string.Format("序列号:{0} 测试中止", Serial));
  829. }
  830. public event DltShowMsg MessageEvent;
  831. /// <summary>
  832. /// 本对象显示消息,以及测试指标显示消息都经过这个方法
  833. /// </summary>
  834. /// <param name="msgType"></param>
  835. /// <param name="msg"></param>
  836. void ShowMessage(MsgType msgType, string msg)
  837. {
  838. if(MessageEvent != null)
  839. {
  840. MessageEvent(msgType, msg);
  841. }
  842. //if (msgType == MsgType.Notice || msgType == MsgType.Error)
  843. if (msgType == MsgType.Error)
  844. {
  845. MessageBox.Show(msg);
  846. }
  847. }
  848. public void ResetTestTable()
  849. {
  850. if(this.InitTestTable != null)
  851. {
  852. TestTable = this.InitTestTable.Copy();
  853. }
  854. }
  855. public void ResetManualTable()
  856. {
  857. if (this.InitManualTable != null)
  858. {
  859. ManualTable = this.InitManualTable.Copy();
  860. }
  861. }
  862. public AppLibs.Devices.IVISA GetDevice(string name)
  863. {
  864. DeviceNode node = this.Devices.FirstOrDefault(x => x.DeviceName == name);
  865. //不存在或者状态不对,都返回空
  866. if(node == null || node.State == false)
  867. {
  868. return null;
  869. }
  870. else
  871. {
  872. AppLibs.Devices.IDeviceHost devHost = Bundle.host.GetFirstOrDefaultService<AppLibs.Devices.IDeviceHost>();
  873. if (devHost == null)
  874. return null;
  875. DeviceParameter dev = devHost.GetFirstOrDefaultDeviceID(node.DeviceHandle);
  876. //要地址,名称,型号一致
  877. if (dev == null || !(node.DeviceType == dev.DeviceType && node.DeviceModel == dev.DeviceModel))
  878. {
  879. return null;
  880. }
  881. else
  882. {
  883. return (IVISA)dev;
  884. }
  885. }
  886. }
  887. public AppLibs.Devices.IVISA GetDeviceModel(string DeviceHandle)
  888. {
  889. DeviceNode node = this.Devices.FirstOrDefault(x => x.DeviceHandle == DeviceHandle);
  890. //不存在或者状态不对,都返回空
  891. if (node == null && node.State == false)
  892. {
  893. return null;
  894. }
  895. else
  896. {
  897. AppLibs.Devices.IDeviceHost devHost = Bundle.host.GetFirstOrDefaultService<AppLibs.Devices.IDeviceHost>();
  898. if (devHost == null)
  899. return null;
  900. DeviceParameter dev = devHost.GetFirstOrDefaultDeviceID(node.DeviceHandle);
  901. //要地址,名称,型号一致
  902. //if (dev == null || !(node.DeviceType == dev.DeviceType && node.DeviceModel == dev.DeviceModel))
  903. //if (dev == null || !(node.DeviceType == dev.DeviceType ))
  904. if (dev == null)
  905. {
  906. return null;
  907. }
  908. else
  909. {
  910. return (IVISA)dev;
  911. }
  912. }
  913. }
  914. public void SetManualTableCellValue(int row, int col, bool ok, object value)
  915. {
  916. if (ManualTableCellChanged != null)
  917. ManualTableCellChanged(row, col,ok, value);
  918. }
  919. public void SetTestTableCellValue(int row, int col, bool ok, object value)
  920. {
  921. if (TestTableCellChanged != null)
  922. TestTableCellChanged(row, col, ok, value);
  923. }
  924. public void TestTableAddCell(string series, string name,string systemch, string lower, string upper, string testval,string result)
  925. {
  926. if (AddTestTableCell != null)
  927. AddTestTableCell(series,name,systemch,lower,upper,testval,result);
  928. }
  929. public void UpDateCurrentSeries(string CuurentSeries)
  930. {
  931. if (CurrentSeries != null )
  932. {
  933. CurrentSeries(CuurentSeries);
  934. }
  935. }
  936. void SaveTestTable()
  937. {
  938. //if(string.IsNullOrEmpty(Serial))
  939. //{
  940. // ShowMessage(MsgType.Info, "序列号为空,数据不保存");
  941. // return;
  942. //}
  943. //AppLibs.Function.IReportHost report = Bundle.host.GetFirstOrDefaultService<AppLibs.Function.IReportHost>();
  944. //if(report != null)
  945. //{
  946. // AppLibs.Models.TableInfo tableInfo = new AppLibs.Models.TableInfo();
  947. // tableInfo.data = TestTable;
  948. // tableInfo.table = new AppLibs.Models.Table();
  949. // tableInfo.table.Result = "合格";
  950. // tableInfo.table.Temperature = Temperature;
  951. // tableInfo.table.Tester = Tester;
  952. // tableInfo.table.Time = DateTime.Now;
  953. // tableInfo.table.Place = Place;
  954. // tableInfo.table.Serial = Serial;
  955. // tableInfo.table.Humidity = Humidity;
  956. // tableInfo.table.Type = TestProject;
  957. // tableInfo.table.ProductCode = Product;
  958. // tableInfo.table.ProductName = Product;
  959. // tableInfo.table.Name = TestProject + "#" + Product;
  960. // try
  961. // {
  962. // if (report.WriteAndReplaceTable(tableInfo))
  963. // {
  964. // ShowMessage(MsgType.Info, "自动测试记录表保存成功");
  965. // }
  966. // else
  967. // {
  968. // ShowMessage(MsgType.Info, "自动测试记录表保存失败");
  969. // }
  970. // }
  971. // catch (Exception ex)
  972. // {
  973. // ShowMessage(MsgType.Error, "自动测试记录表保存失败");
  974. // }
  975. //}
  976. //else
  977. //{
  978. // ShowMessage(MsgType.Info, "软件未包含数据存储模块");
  979. //}
  980. }
  981. //判断某个测试项是否勾选
  982. public bool IsTestItemSelected(string channel , string name)
  983. {
  984. var node = this.TestNodes.FirstOrDefault(x => x.Channel == channel && x.Name == name);
  985. if (node == null)
  986. return false;
  987. return node.IsSelected;
  988. }
  989. #endregion
  990. #region 二次修改的方法
  991. //test
  992. #endregion
  993. }
  994. }