MainTps.cs 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129
  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. ShowMessage(MsgType.Info, string.Format("关闭6YYC信号源,关闭串口,关闭内部蚯蚓电源."));
  622. }
  623. }
  624. /// <summary>
  625. /// 开始测试
  626. /// </summary>
  627. /// <param name="isOrderByChannel">按照指标分组还是按照通道分组</param>
  628. public void Start(bool isOrderByChannel,string[] ProductSeries, CommonVisaResource DCPower, RainwormPower rainwormPower, TransmitterSerialPort SerialClient, MatchComPara CfigComParas)
  629. {
  630. isStop = false;
  631. //清空测试数据
  632. // BaseModel.TestResults.Clear();
  633. // FrmMain FrmPara = new FrmMain();
  634. byte FourthByte = 0x00;
  635. string ComPort = CfigComParas.GetComPort("1");
  636. byte ThridByte = Convert.ToByte(CfigComParas.GetThirdByte("1"), 16);
  637. int FrequencyNumber = 0;
  638. if (TestFreqSum >= CfigComParas.ComParameters.Count)//如果限定的测试频点数大于设置的频点数
  639. {
  640. FrequencyNumber = CfigComParas.ComParameters.Count;//取设置的频点数
  641. }
  642. else
  643. {
  644. FrequencyNumber = TestFreqSum;//取限定的测试频点数
  645. }
  646. int ControlDelay = this.TestNodes[0].Parameters.GetParameter<int>("控制延时");
  647. for (int i = 0; i < ProductSeries.Length; i++)
  648. {
  649. if (FrmMain.ProdEnabCh[i]==true)//启用的路才加电
  650. {
  651. FrmMain.dio.SupplySwitch(i + 1, DioControlClass.State.ON);//打开产品供电开关
  652. }
  653. else
  654. {
  655. FrmMain.dio.SupplySwitch(i + 1, DioControlClass.State.OFF);//打开产品供电开关
  656. }
  657. }
  658. //SerialClient.SerialOpen(CfigComParas.GetComPort("1"));
  659. //ShowMessage(MsgType.Info, string.Format("打开串口."));
  660. //选择勾选项
  661. List<TestNode> nodes = this.TestNodes.Where(x => x.IsSelected == true).ToList();
  662. if (isOrderByChannel)
  663. {
  664. //按照通道分组
  665. Stopwatch TimesCounter = new Stopwatch();
  666. double testMin = 0;
  667. TimesCounter.Restart();
  668. int Channel = 1;
  669. foreach (IGrouping<string, TestNode> group in nodes.GroupBy(x => x.Channel))
  670. {
  671. if (nodes.Count == 2)
  672. {
  673. if (group.Key == nodes[0].Channel)
  674. {
  675. MessageBox.Show("将产品通道1输出电缆接【衰减】接口,产品通道2输出电缆接【陷波】接口。", "温馨提示");
  676. }
  677. else if (group.Key == nodes[1].Channel)
  678. {
  679. MessageBox.Show("将产品通道1输出电缆接【陷波】接口,产品通道2输出电缆接【衰减】接口。", "温馨提示");
  680. }
  681. }
  682. else if(nodes.Count == 1)
  683. {
  684. MessageBox.Show("将产品输出电缆接【衰减】接口。", "温馨提示");
  685. }
  686. //channel++;
  687. //排序后执行
  688. for (int point = 0; point < FrequencyNumber; point++)//频点总数
  689. {
  690. FourthByte = Convert.ToByte(CfigComParas.GetFourthByte((point + 1).ToString()), 16);
  691. double CenterFreq = double.Parse(CfigComParas.Getfreqpoint((point + 1).ToString()));
  692. for (int i = 0; i < this.TestNodes.Count; i++)
  693. {
  694. this.TestNodes[i].PointIndex = point;
  695. this.TestNodes[i].CenterFreq = CenterFreq;
  696. this.TestNodes[i].PointTotal = FrequencyNumber;
  697. }
  698. //if (FrmPara.IsRuning == false)//中途点击停止测试按钮
  699. //{
  700. // //控制断电
  701. // StopClose(ProductSeries, DCPower, rainwormPower, SerialClient);
  702. // return;
  703. //}
  704. //控制
  705. if (Product.Contains("YZH16A"))//针对YZH16A的产品
  706. {
  707. SerialClient.DUT_Transmitter_Ctrol(ThridByte, FourthByte, 0x55);//todo:切换频点
  708. }
  709. else
  710. {
  711. SerialClient.DUT_Transmitter_Ctrol1(ThridByte, FourthByte);//todo:切换频点
  712. }
  713. ShowMessage(MsgType.Info, string.Format("发送串口指令EB 90 {0} {1}.", ThridByte, FourthByte));
  714. testMin = TimesCounter.ElapsedMilliseconds / 1000f / 60f;
  715. Thread.Sleep(ControlDelay);//单位ms
  716. ShowMessage(MsgType.Info, string.Format("延时{0}ms.", ControlDelay));
  717. RemainTimeUpdate(group.Key, point, FrequencyNumber, CenterFreq, testMin);
  718. //Tps_LQ_Transmitter.FrmMain.BeginInvoke(new Action(() =>
  719. //{
  720. // //labRemainTime.Text = $"第{point + 1}个频点[{CenterFreq}]MHz测试,共{currFileNode.Tps.TestNodes.Count - 1}个频点,耗时{Math.Round(testMin, 2)}Min。";
  721. //}));
  722. //Tps_LQ_Transmitter.FrmMain.BeginInvoke(new FrmMain RemainTime, point, CenterFreq, testMin);
  723. // //labRemainTime.Text = $"第{point + 1}个频点[{CenterFreq}]MHz测试,共{currFileNode.Tps.TestNodes.Count - 1}个频点,耗时{Math.Round(testMin, 2)}Min。";
  724. foreach (TestNode testnode in group.OrderBy(a => a.Order))
  725. {
  726. //if (FrmPara.IsRuning == false)//中途点击停止测试按钮
  727. //{
  728. // //控制断电
  729. // StopClose(ProductSeries, DCPower, rainwormPower, SerialClient);
  730. // return;
  731. //}
  732. if (isStop == false)
  733. {
  734. if (nodes.Count == 1 && testnode.Name.Contains("杂波抑制"))
  735. {
  736. MessageBox.Show("将产品输出电缆接【陷波】接口。", "温馨提示");
  737. }
  738. if (nodes.Count == 2 && testnode.Name.Contains("杂波抑制"))
  739. {
  740. if (group.Key == nodes[0].Channel)
  741. {
  742. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", nodes[1].Channel, testnode.Name));
  743. }
  744. else if (group.Key == nodes[1].Channel)
  745. {
  746. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", nodes[0].Channel, testnode.Name));
  747. }
  748. }
  749. else
  750. {
  751. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", testnode.Channel, testnode.Name));
  752. }
  753. if (testnode.TestModel != null)
  754. {
  755. if (testnode.IsSelected)
  756. {
  757. currModel = testnode.TestModel;
  758. for (int i =0;i< ProductSeries.Length;i++) //各路分别测试
  759. {
  760. if (FrmMain.ProdEnabCh[i] == true) //启用的路才进行测试
  761. {
  762. //if (FrmPara.IsRuning == false)//中途点击停止测试按钮
  763. //{
  764. // //控制断电
  765. // StopClose(ProductSeries, DCPower, rainwormPower, SerialClient);
  766. // return;
  767. //}
  768. Thread.Sleep(500);
  769. this.Serial = ProductSeries[i];
  770. SystemChofSerial = (Array.IndexOf(ProductSeries, ProductSeries[i]) + 1).ToString();
  771. UpDateCurrentSeries(this.Serial);
  772. // 陷波支路用于测杂波抑制,衰减支路用于测试其他指标,
  773. //双通道测试时:当测通道1的衰减支路指标时,在不换线的情况下,则进行通道2的陷波支路指标,然后换线,测通道2的衰减支路指标时,在不换线的情况下,则进行通道1的陷波支路指标。
  774. //单通道测试时,当测通道1的衰减支路指标时,换线后,单独测试通道1的陷波支路指标
  775. FrmMain.dio.OneToEight(i + 1, DioControlClass.State.ON);
  776. ShowMessage(MsgType.Info, string.Format("切换至第{0}路 " ,i+1));
  777. if (testnode.Name.Contains("杂波抑制"))
  778. {
  779. //todo:切产品同时切到陷波支路(1切8射频开关,1切2射频开关)
  780. FrmMain.gpio.AllSwitchBandstopft();//8路全切至陷波器
  781. ShowMessage(MsgType.Info, "射频开关切换至陷波器");
  782. }
  783. else
  784. {
  785. //todo:切产品同时切到衰减支路(1切8射频开关,1切2射频开关)
  786. FrmMain.gpio.AllSwitchAttenuator();//8路全切至衰减器
  787. ShowMessage(MsgType.Info, "射频开关切换至衰减器");
  788. }
  789. if (testnode.Name.Contains("功率(功率计)"))//功率测试需接入功率计其余使用频谱仪测试
  790. {
  791. FrmMain.dio.RfSwitchX("功率计");//接入功率计
  792. ShowMessage(MsgType.Info, "射频开关切换功率计仪接入");
  793. }
  794. else
  795. {
  796. FrmMain.dio.RfSwitchX("频谱仪");//接入频谱仪
  797. ShowMessage(MsgType.Info, "射频开关切换频谱仪接入");
  798. }
  799. Thread.Sleep(500);//射频开关切换后延时
  800. testnode.TestModel.Start(testnode, nodes);
  801. }
  802. }
  803. }
  804. }
  805. else
  806. {
  807. ShowMessage(MsgType.Error, string.Format("测试指标:{0}/{1} 没有实例化执行模块", testnode.Channel, testnode.Name));
  808. }
  809. }
  810. else
  811. {
  812. break;
  813. }
  814. }
  815. }
  816. }
  817. }
  818. else
  819. {
  820. //按照指标名称进行
  821. foreach (IGrouping<string, TestNode> group in nodes.GroupBy(x => x.Name))
  822. {
  823. //排序后执行
  824. foreach (TestNode testnode in group.OrderBy(a => a.Order))
  825. {
  826. if (isStop == false)
  827. {
  828. ShowMessage(MsgType.Info, string.Format("开始执行测试指标:{0}/{1}", testnode.Channel, testnode.Name));
  829. if (testnode.TestModel != null)
  830. {
  831. currModel = testnode.TestModel;
  832. // testnode.TestModel.Start(testnode);
  833. }
  834. else
  835. {
  836. ShowMessage(MsgType.Error, string.Format("测试指标:{0}/{1} 没有实例化执行模块", testnode.Channel, testnode.Name));
  837. }
  838. }
  839. else
  840. {
  841. break;
  842. }
  843. }
  844. }
  845. }
  846. for (int i = 0; i < ProductSeries.Length; i++)
  847. {
  848. FrmMain.dio.SupplySwitch(i + 1, DioControlClass.State.OFF);//关闭产品供电开关
  849. }
  850. //保存自动测试记录表
  851. SaveTestTable();
  852. ShowMessage(MsgType.Info, string.Format("序列号:{0} 测试完成", Serial));
  853. }
  854. bool isStop = false;
  855. BaseModel currModel = null;
  856. public void Stop()
  857. {
  858. isStop = true;
  859. if(currModel!= null)
  860. {
  861. currModel.Stop();
  862. }
  863. ShowMessage(MsgType.Info, string.Format("序列号:{0} 测试中止", Serial));
  864. }
  865. public event DltShowMsg MessageEvent;
  866. /// <summary>
  867. /// 本对象显示消息,以及测试指标显示消息都经过这个方法
  868. /// </summary>
  869. /// <param name="msgType"></param>
  870. /// <param name="msg"></param>
  871. void ShowMessage(MsgType msgType, string msg)
  872. {
  873. if(MessageEvent != null)
  874. {
  875. MessageEvent(msgType, msg);
  876. }
  877. //if (msgType == MsgType.Notice || msgType == MsgType.Error)
  878. if (msgType == MsgType.Error)
  879. {
  880. MessageBox.Show(msg);
  881. }
  882. }
  883. public void ResetTestTable()
  884. {
  885. if(this.InitTestTable != null)
  886. {
  887. TestTable = this.InitTestTable.Copy();
  888. }
  889. }
  890. public void ResetManualTable()
  891. {
  892. if (this.InitManualTable != null)
  893. {
  894. ManualTable = this.InitManualTable.Copy();
  895. }
  896. }
  897. public AppLibs.Devices.IVISA GetDevice(string name)
  898. {
  899. DeviceNode node = this.Devices.FirstOrDefault(x => x.DeviceName == name);
  900. //不存在或者状态不对,都返回空
  901. if(node == null || node.State == false)
  902. {
  903. return null;
  904. }
  905. else
  906. {
  907. AppLibs.Devices.IDeviceHost devHost = Bundle.host.GetFirstOrDefaultService<AppLibs.Devices.IDeviceHost>();
  908. if (devHost == null)
  909. return null;
  910. DeviceParameter dev = devHost.GetFirstOrDefaultDeviceID(node.DeviceHandle);
  911. //要地址,名称,型号一致
  912. if (dev == null || !(node.DeviceType == dev.DeviceType && node.DeviceModel == dev.DeviceModel))
  913. {
  914. return null;
  915. }
  916. else
  917. {
  918. return (IVISA)dev;
  919. }
  920. }
  921. }
  922. public AppLibs.Devices.IVISA GetDeviceModel(string DeviceHandle)
  923. {
  924. DeviceNode node = this.Devices.FirstOrDefault(x => x.DeviceHandle == DeviceHandle);
  925. //不存在或者状态不对,都返回空
  926. if (node == null && node.State == false)
  927. {
  928. return null;
  929. }
  930. else
  931. {
  932. AppLibs.Devices.IDeviceHost devHost = Bundle.host.GetFirstOrDefaultService<AppLibs.Devices.IDeviceHost>();
  933. if (devHost == null)
  934. return null;
  935. DeviceParameter dev = devHost.GetFirstOrDefaultDeviceID(node.DeviceHandle);
  936. //要地址,名称,型号一致
  937. //if (dev == null || !(node.DeviceType == dev.DeviceType && node.DeviceModel == dev.DeviceModel))
  938. //if (dev == null || !(node.DeviceType == dev.DeviceType ))
  939. if (dev == null)
  940. {
  941. return null;
  942. }
  943. else
  944. {
  945. return (IVISA)dev;
  946. }
  947. }
  948. }
  949. public void SetManualTableCellValue(int row, int col, bool ok, object value)
  950. {
  951. if (ManualTableCellChanged != null)
  952. ManualTableCellChanged(row, col,ok, value);
  953. }
  954. public void SetTestTableCellValue(int row, int col, bool ok, object value)
  955. {
  956. if (TestTableCellChanged != null)
  957. TestTableCellChanged(row, col, ok, value);
  958. }
  959. public void TestTableAddCell(string series, string name,string systemch, string lower, string upper, string testval,string result)
  960. {
  961. if (AddTestTableCell != null)
  962. AddTestTableCell(series,name,systemch,lower,upper,testval,result);
  963. }
  964. public void UpDateCurrentSeries(string CuurentSeries)
  965. {
  966. if (CurrentSeries != null )
  967. {
  968. CurrentSeries(CuurentSeries);
  969. }
  970. }
  971. void SaveTestTable()
  972. {
  973. //if(string.IsNullOrEmpty(Serial))
  974. //{
  975. // ShowMessage(MsgType.Info, "序列号为空,数据不保存");
  976. // return;
  977. //}
  978. //AppLibs.Function.IReportHost report = Bundle.host.GetFirstOrDefaultService<AppLibs.Function.IReportHost>();
  979. //if(report != null)
  980. //{
  981. // AppLibs.Models.TableInfo tableInfo = new AppLibs.Models.TableInfo();
  982. // tableInfo.data = TestTable;
  983. // tableInfo.table = new AppLibs.Models.Table();
  984. // tableInfo.table.Result = "合格";
  985. // tableInfo.table.Temperature = Temperature;
  986. // tableInfo.table.Tester = Tester;
  987. // tableInfo.table.Time = DateTime.Now;
  988. // tableInfo.table.Place = Place;
  989. // tableInfo.table.Serial = Serial;
  990. // tableInfo.table.Humidity = Humidity;
  991. // tableInfo.table.Type = TestProject;
  992. // tableInfo.table.ProductCode = Product;
  993. // tableInfo.table.ProductName = Product;
  994. // tableInfo.table.Name = TestProject + "#" + Product;
  995. // try
  996. // {
  997. // if (report.WriteAndReplaceTable(tableInfo))
  998. // {
  999. // ShowMessage(MsgType.Info, "自动测试记录表保存成功");
  1000. // }
  1001. // else
  1002. // {
  1003. // ShowMessage(MsgType.Info, "自动测试记录表保存失败");
  1004. // }
  1005. // }
  1006. // catch (Exception ex)
  1007. // {
  1008. // ShowMessage(MsgType.Error, "自动测试记录表保存失败");
  1009. // }
  1010. //}
  1011. //else
  1012. //{
  1013. // ShowMessage(MsgType.Info, "软件未包含数据存储模块");
  1014. //}
  1015. }
  1016. //判断某个测试项是否勾选
  1017. public bool IsTestItemSelected(string channel , string name)
  1018. {
  1019. var node = this.TestNodes.FirstOrDefault(x => x.Channel == channel && x.Name == name);
  1020. if (node == null)
  1021. return false;
  1022. return node.IsSelected;
  1023. }
  1024. #endregion
  1025. #region 二次修改的方法
  1026. //test
  1027. #endregion
  1028. }
  1029. }