/// <summary> /// 得到指定 POE 文件的功能块描述信息。 /// </summary> /// <param name="fileName">POE 文件名称</param> /// <param name="reader">文本文件读对象</param> /// <returns>功能块描述信息,null 表示失败。</returns> public static ViPOEBlockType GetBlockType(string fileName, TextReader reader) { ViPOEBlockType blockType = null; ViConnType connType = null; int lineIndex = 0; // 0x00: 没有读取到功能块开始 // 0x01: 读取到功能块开始 // 0x21: 开始 INPUT // 0x22: 开始 OUTPUT // 0x23: 开始 IN_OUT int stage = 0; while (true) { string line = reader.ReadLine(); if (line == null) { break; } ++lineIndex; line = line.Trim(); if (string.IsNullOrEmpty(line)) { continue; } if (stage == 0x00) { if (line.StartsWith("FUNCTION_BLOCK ", StringComparison.OrdinalIgnoreCase)) { connType = ViConnType.Parse(line.Substring(15), ViTypeCreation.None); if (connType != null && connType.Type == null) { blockType = new ViPOEBlockType(connType.Name, null); blockType.Comment = connType.Comment; // stage = 0x01; } else { Trace.WriteLine(string.Format("{0}({1}): Invalid FUNCTION_BLOCK declaration!", fileName, lineIndex)); } } //else if (line.StartsWith("PROGRAM ", StringComparison.OrdinalIgnoreCase)) //{ // connType = ViConnType.Parse(line.Substring(8), ViTypeCreation.None); // if (connType != null && connType.Type == null) // { // blockType = new ViPOEBlockType(connType.Name, null); // blockType.Comment = connType.Comment; // // // stage = 0x01; // } // else // { // Trace.WriteLine(string.Format("{0}({1}): Invalid PROGRAM declaration!", fileName, lineIndex)); // } //} else if (line.StartsWith("FUNCTION ", StringComparison.OrdinalIgnoreCase)) { connType = ViConnType.Parse(line.Substring(9), ViTypeCreation.Create); if (connType != null && connType.Type != null) { blockType = new ViPOEBlockType(connType.Name, connType.Type); blockType.Comment = connType.Comment; // stage = 0x01; } else { Trace.WriteLine(string.Format("{0}({1}): Invalid FUNCTION declaration!", fileName, lineIndex)); } } } else if (stage >= 0x01) { if (stage == 0x01 && line.EndsWith("*)") && line.StartsWith("(* task usage:", StringComparison.OrdinalIgnoreCase)) { blockType.ModesDecl = line.Substring(14, line.Length - 16); } else if (line.StartsWith(ViTextFile.CommentBegin)) { // 注释行 } else if (line.StartsWith("VAR_INPUT", StringComparison.OrdinalIgnoreCase)) { stage = 0x21; } else if (line.StartsWith("VAR_OUTPUT", StringComparison.OrdinalIgnoreCase)) { stage = 0x22; } else if (line.StartsWith("VAR_IN_OUT", StringComparison.OrdinalIgnoreCase)) { stage = 0x23; } else if (line.StartsWith("END_VAR", StringComparison.OrdinalIgnoreCase)) { stage = 0x01; } else if (line.StartsWith("LD ", StringComparison.OrdinalIgnoreCase)) { break; } else if (line.StartsWith("END_FUNCTION", StringComparison.OrdinalIgnoreCase)) { if (blockType != null) { // 功能块后缀描述字符串 blockType.SetSuffixDecl(line); } break; } else if (stage >= 0x21) { connType = ViConnType.Parse(line, ViTypeCreation.Create); if (connType != null && connType.Type != null) { switch ((stage & 0x0F)) { case 0x01: // INPUT connType.SetParent(blockType); blockType.InputConnectors.Add(connType); break; case 0x02: // OUTPUT connType.SetParent(blockType); blockType.OutputConnectors.Add(connType); break; case 0x03: // IN_OUT connType.SetParent(blockType); blockType.InputConnectors.Insert(blockType.InOutConnectorCount, connType); blockType.OutputConnectors.Insert(blockType.InOutConnectorCount, connType); blockType.InOutConnectorCount = blockType.InOutConnectorCount + 1; break; } } else { Trace.WriteLine(string.Format("{0}({1}): Invalid connection declaration!", fileName, lineIndex)); } } } } return(blockType); }
/// <summary> /// 更新功能块数组列表。 /// </summary> public override void UpdatePOUs() { // 当CPU为null的时候,有可能当前类还未初始化完毕; if (this.CPU == null) { return; } this.DeleteAll(); IniFile iniFile = new IniFile(this.SourceFile); string projectPath = FileName.GetFilePath(this.SourceFile); int sectionType = 0; // 0 不关心;2 POE;9 LIBRARY iniFile.LoopSections((section) => { if (section.EndsWith("_FUNCTIONBLOCK", StringComparison.OrdinalIgnoreCase) || section.EndsWith("_FUNCTION", StringComparison.OrdinalIgnoreCase)) { sectionType = 2; return(true); } if (string.Equals(section, "LIBRARY", StringComparison.OrdinalIgnoreCase)) { sectionType = 9; return(true); } sectionType = 0; return(false); }, (key, value) => { if (!string.IsNullOrEmpty(value) && key.IsPrefixIndex("FILE")) { string file, hardwareType; switch (sectionType) { case 2: // 工程本身的功能块 { file = FileName.GetAbsoluteFileName(projectPath, value); file = FileName.GetNewExtFileName(file, ".POE"); hardwareType = ViGlobal.GetPathHardwareName(projectPath, file); // 没有硬件类型名称,或者硬件类型名称匹配的情况下,才将功能块加入 if (string.IsNullOrEmpty(hardwareType) || string.Equals(hardwareType, this.CPU.HardwareType, StringComparison.OrdinalIgnoreCase)) { ViPOEBlockType blockType = ViIECPOEFile.GetBlockType(file); if (blockType != null) { blockType.PouSource = this; this.AddChild(blockType); } } } break; case 9: // 工程使用的 ViGET 库工程的功能块 { file = FileName.GetAbsoluteFileName(ViGlobal.ProjODKPath, value); file = FileName.GetNewExtFileName(file, ".VAR"); // 不能讲把自身作为一个库文件来使用,否则会造成死循环; if (this.CPU.ProjectFile != null && !this.CPU.ProjectFile.Equals(file, StringComparison.OrdinalIgnoreCase)) { ViPouSourceCPU cpu = new ViPouSourceCPU() { ProjectFile = file, HardwareType = this.CPU.HardwareType, }; ViCPUPouSource cpuSource = new ViCPUPouSource(cpu, ViPouAttributes.ProjectLibrary | (this.PouAttributes & ViPouAttributes.Public)); if (cpuSource != null) { this.AddChild(cpuSource); } } } break; } } return(true); }); // CPU 安装的硬件库的功能块 if (!string.IsNullOrEmpty(this.CPU.CPUName)) { string globProt = ViGlobal.GetCPUENVPath(projectPath, this.CPU.CPUName) + "GLOBPROT.INC"; string infoFile = ViGlobal.GetCPUENVPath(projectPath, this.CPU.CPUName) + this.CPU.HardwareType + ".ini"; this.AddChild(new ViIncPouSource(globProt, infoFile, ViPouAttributes.CPULibrary | (this.PouAttributes & ViPouAttributes.Public))); } // ViGET 全局的功能块。对于安装的库工程,就不要这些信息了,否则就重复了 if (!string.IsNullOrEmpty(this.CPU.CPUName)) { ArrayList alPouSources = ViGlobal.GetPouSources(this.CPU.HardwareType); if (alPouSources != null) { foreach (ViPouSource source in alPouSources) { this.AddChild(source); } } } }