public static void Create(IEnumerable <IBlock> blocks, string path, PortalPlc owningPlc) { if (blocks == null) { throw new ArgumentNullException(nameof(blocks)); } IEnumerable <DataBlock> dataBlocks; if ((dataBlocks = blocks.OfType <DataBlock>())?.Count() <= 0) { throw new ArgumentException("Blocks does not contain any valid DataBlocks.", nameof(blocks)); } KepwareConfiguration.CreateInternal(dataBlocks, path, owningPlc); }
public static void Create(IEnumerable <IBlock> blocks, string path, PortalPlc parentPlc, WinccExportType exportType, TiaPortalVersion portalVersion) { if (blocks == null) { throw new ArgumentNullException(nameof(blocks)); } IEnumerable <DataBlock> dataBlocks; if ((dataBlocks = blocks.OfType <DataBlock>())?.Count() <= 0) { throw new ArgumentException("Blocks does not contain any valid DataBlocks.", nameof(blocks)); } WinccConfiguration.CreateInternal(dataBlocks, path, parentPlc, exportType, portalVersion); }
public static void Create(IEnumerable <IBlock> blocks, string path, PortalPlc parentPlc, AlarmworxSettings settings) { if (blocks == null) { throw new ArgumentNullException(nameof(blocks)); } IEnumerable <DataBlock> dataBlocks; if ((dataBlocks = blocks.OfType <DataBlock>())?.Count() <= 0) { throw new ArgumentException("Blocks does not contain any valid DataBlocks.", nameof(blocks)); } AlarmWorxConfiguration.CreateInternal(dataBlocks, path, parentPlc, settings); }
public static void ResolveArrayChildren(DataEntry entry, PortalPlc parentPlc) { if (entry.DataType != DataType.ARRAY) { return; } var arrayStart = parentPlc?.GetConstantValue(entry.ArrayStartIndex) ?? entry.ArrayStartIndex.Value; var arrayEnd = parentPlc?.GetConstantValue(entry.ArrayEndIndex) ?? entry.ArrayEndIndex.Value; _ = entry.ArrayDataEntry.CalculateSize(parentPlc); entry.Children = new LinkedList <DataEntry>(); // First populate the array Children with the correct number and type of children for (var i = arrayStart; i <= arrayEnd; i++) { entry.Children.AddLast(new DataEntry(entry.Name + $"[{i}]", entry.ArrayDataEntry.DataType, entry.Comment + $" ({i})", entry.ArrayDataEntry.Children, entry.ArrayDataEntry.DataTypeName, entry.ArrayDataEntry.StringLength)); } // re-calculate the addresses of the children entry.CalcluateAddresses(parentPlc); }
private static void CreateInternal(IEnumerable <DataBlock> dataBlocks, string path, string opcServerPrefix, PortalPlc parentPlc) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (!FileHelpers.IsValidFilePath(path, ".csv")) { throw new ArgumentException(path + " is not a valid path.", nameof(path)); } try { using (var file = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(file)) { AlarmWorxConfiguration.WriteHeaders(writer); foreach (var block in dataBlocks) { if (block == null) { throw new ArgumentNullException(nameof(block)); } if (block.Children?.Count <= 0) { throw new ArgumentException("Block '" + block.Name + "' contains no data", nameof(block)); } foreach (var child in block) { WriteAlarmRow(writer, child, block.Name + ".", block.Comment); } } AlarmWorxConfiguration.WriteFooter(writer); writer.Flush(); } } catch (Exception e) { throw new SiemensException("Could not write AlarmWorX configuration", e); } void WriteAlarmRow(StreamWriter writer, DataEntry entry, string prependNameText, string prependCommentText) { string stackedComment; if (string.IsNullOrWhiteSpace(prependCommentText)) { stackedComment = entry.Comment.Replace(",", "-"); } else if (prependCommentText.EndsWith(" - ")) { stackedComment = prependCommentText + entry.Comment; } else { stackedComment = prependCommentText + " - " + entry.Comment; } switch (entry.DataType) { case DataType.ARRAY: TagHelper.ResolveArrayChildren(entry, parentPlc); foreach (var child in entry.Children) { WriteAlarmRow(writer, child, prependNameText, prependNameText); } break; case DataType.STRUCT: foreach (var child in entry.Children) { WriteAlarmRow(writer, child, prependNameText + entry.Name + ".", stackedComment); } break; case DataType.UDT: foreach (var child in parentPlc.UserDataTypes.FirstOrDefault(u => u.Name == entry.DataTypeName)) { WriteAlarmRow(writer, child, prependNameText + entry.Name + ".", stackedComment); } break; case DataType.BOOL: var row = new AlarmWorxRow { LocationPath = @"\\Alarm Configurations\" + ALARM_FOLDER, Name = ALARM_FOLDER + "." + prependNameText + entry.Name, Description = stackedComment, LastModified = DateTime.Now.ToString(), Input1 = opcServerPrefix + "\\" + prependNameText + entry.Name, BaseText = stackedComment, // Message text DigMessageText = " ", // Prevents 'Digital Alarm' text at the end of each message DigLimit = "1", // Alarm state value needs to be 1 for a digital DigSeverity = "500", // Default severity is 500 DigRequiresAck = "1" // Require an acknowledge by default }; writer.WriteLine(row.ToString()); break; default: throw new ArgumentException("Cannot export datatype: " + entry.DataType.ToString() + " to AlarmWorX configuration"); } } }
public static void Create(DataBlock block, string path, string opcServerPrefix, PortalPlc parentPlc) { AlarmWorxConfiguration.Create(new[] { block }, path, opcServerPrefix, parentPlc); }
private static void CreateInternal(IEnumerable <DataBlock> dataBlocks, string path, PortalPlc parentPlc, WinccExportType exportType, TiaPortalVersion portalVersion) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (!FileHelpers.IsValidFilePath(path, ".xlsx")) { throw new ArgumentException(path + " is not a valid path.", nameof(path)); } var currentAlarmRow = 2; var currentTagRow = 2; string dataBlockName; var proTags = new List <string>(); using (var document = new ExcelPackage()) { var tagWorksheet = document.Workbook.Worksheets.Add(TagWorksheetName); var alarmWorksheet = document.Workbook.Worksheets.Add(AlarmWorksheetName); WinccConfiguration.WriteXlsxHeaders(document.Workbook, exportType, portalVersion); foreach (var db in dataBlocks) { dataBlockName = db.Name; db.CalcluateAddresses(parentPlc); foreach (var entry in db.Children) { ProcessDataEntry(alarmWorksheet, entry, string.Empty, new Address(), db.Name); } if (exportType != WinccExportType.Professional) { WriteComfortAdvancedTagRow(tagWorksheet, db, "HMI_Connection_1"); } } if (exportType == WinccExportType.Professional) { foreach (var tag in proTags) { WriteProfessionalTagRow(tagWorksheet, tag, "HMI_Connection_1"); } } using (Stream file = new FileStream(path, FileMode.Create)) { document.SaveAs(file); } } void ProcessDataEntry(ExcelWorksheet worksheet, DataEntry entry, string prependText, Address addressOffset, string prependTag = "") { string stackedComment; if (string.IsNullOrWhiteSpace(prependText)) { stackedComment = entry.Comment; } else if (prependText.EndsWith(" - ")) { stackedComment = prependText + entry.Comment; } else { stackedComment = prependText + " - " + entry.Comment; } string stackedTag; if (string.IsNullOrWhiteSpace(prependTag)) { stackedTag = entry.Name; } else if (prependText.EndsWith(".")) { stackedTag = prependTag + entry.Name; } else { stackedTag = prependTag + "." + entry.Name; } switch (entry.DataType) { case DataType.BOOL: var alarmNumber = currentAlarmRow - 1; var row = WinccConstants.GetAlarmRow(exportType, portalVersion); row[WinccExportField.Id] = alarmNumber.ToString(); row[WinccExportField.Name] = $"Discrete_alarm_{alarmNumber}"; row[WinccExportField.AlarmText] = stackedComment; row[WinccExportField.InfoText] = stackedComment; if (exportType == WinccExportType.Professional) { row[WinccExportField.TriggerTag] = stackedTag.Replace('.', '_'); proTags.Add(stackedTag); } else // WinCC Comfort/Advanced { row[WinccExportField.TriggerTag] = dataBlockName; row[WinccExportField.TriggerBit] = AddressToTriggerBit(addressOffset + entry.Address.Value).ToString(); } var column = 1; foreach (var item in row) { worksheet.Cells[currentAlarmRow, column].Style.Numberformat.Format = "@"; worksheet.Cells[currentAlarmRow, column++].Value = item; } currentAlarmRow++; break; case DataType.UDT: case DataType.STRUCT: entry.CalcluateAddresses(parentPlc); foreach (var newEntry in entry.Children) { ProcessDataEntry(worksheet, newEntry, stackedComment, addressOffset + entry.Address.Value, stackedTag); } break; case DataType.ARRAY: TagHelper.ResolveArrayChildren(entry, parentPlc); // write a new entry for each of the children foreach (var child in entry.Children) { ProcessDataEntry(worksheet, child, prependText, entry.Address.Value + addressOffset, stackedTag); } break; default: throw new SiemensException("Unsupported data type for WinCC alarms: " + entry.Name + ", " + entry.DataType.ToString()); } } void WriteComfortAdvancedTagRow(ExcelWorksheet worksheet, DataBlock dataBlock, string connectionName) { string dataType, address; var dbLength = dataBlock.CalculateSize(parentPlc).Byte; var wordLength = (int)Math.Ceiling(dbLength / 2.0); if (dbLength > 2) { dataType = $"Array [0..{wordLength - 1}] of Word"; address = $"%DB{dataBlock.Number}.DBX0.0"; } else { dataType = "Word"; address = $"%DB{dataBlock.Number}.DBW0"; wordLength = 0; } var row = WinccConstants.GetTagRow(exportType, portalVersion); row[WinccExportField.Name] = dataBlock.Name; row[WinccExportField.Connection] = connectionName; row[WinccExportField.DataType] = dataType; row[WinccExportField.Length] = ((wordLength + 1) * 2).ToString(); row[WinccExportField.Address] = address; var column = 1; foreach (var item in row) { worksheet.Cells[currentTagRow, column].Style.Numberformat.Format = "@"; worksheet.Cells[currentTagRow, column++].Value = item; } currentTagRow++; } void WriteProfessionalTagRow(ExcelWorksheet worksheet, string tag, string connectionName) { var row = WinccConstants.GetTagRow(exportType, portalVersion); row[WinccExportField.Name] = tag.Replace('.', '_'); row[WinccExportField.Connection] = connectionName; row[WinccExportField.PlcTag] = tag; var column = 1; foreach (var item in row) { worksheet.Cells[currentTagRow, column].Style.Numberformat.Format = "@"; worksheet.Cells[currentTagRow, column++].Value = item; } currentTagRow++; } int AddressToTriggerBit(Address address) { if (address.Byte % 2 == 0) { return((address.Byte + 1) * 8 + address.Bit); } else { return((address.Byte - 1) * 8 + address.Bit); } } }
public static void Create(IBlock block, string path, PortalPlc parentPlc, WinccExportType exportType, TiaPortalVersion portalVersion) { WinccConfiguration.Create(new[] { block }, path, parentPlc, exportType, portalVersion); }
private static void ExportDataBlockToFile(DataBlock block, TextWriter writer, PortalPlc parentPlc) { block.CalcluateAddresses(parentPlc); foreach (var entry in block) { AddDataEntry(entry, block.Name + ".", new Address()); } void AddDataEntry(DataEntry entry, string entryPrefix, Address parentOffset) { var addressPrefix = ""; var type = ""; switch (entry.DataType) { case DataType.ARRAY: TagHelper.ResolveArrayChildren(entry, parentPlc); // write a new entry for each of the children foreach (var child in entry.Children) { AddDataEntry(child, entryPrefix, entry.Address.Value + parentOffset); } break; case DataType.BOOL: addressPrefix = "DBX"; type = "Boolean"; break; case DataType.BYTE: addressPrefix = "DBB"; type = "Byte"; break; case DataType.CHAR: addressPrefix = "DBB"; type = "Char"; break; case DataType.DATE: case DataType.DATE_AND_TIME: addressPrefix = "DATE"; type = "Date"; break; case DataType.TIME: case DataType.DINT: addressPrefix = "DBD"; type = "Long"; break; case DataType.DWORD: addressPrefix = "DBD"; type = "Dword"; break; case DataType.INT: addressPrefix = "DBW"; type = "Short"; break; case DataType.REAL: addressPrefix = "DBD"; type = "Float"; break; case DataType.STRING: addressPrefix = "STRING"; type = "String"; break; case DataType.UDT: case DataType.STRUCT: entry.CalcluateAddresses(parentPlc); foreach (var child in entry) { AddDataEntry(child, entryPrefix + entry.Name + ".", entry.Address.Value + parentOffset); } break; case DataType.WORD: addressPrefix = "DBW"; type = "Word"; break; default: throw new SiemensException("Data type: '" + entry.DataType.ToString() + "' not supported."); } if (TagHelper.IsPrimitive(entry.DataType)) { var absoluteAddress = parentOffset + entry.Address.Value; var addressString = "DB" + block.Number + "." + addressPrefix + absoluteAddress.Byte; if (entry.DataType == DataType.BOOL) { addressString += "." + absoluteAddress.Bit; } else if (entry.DataType == DataType.STRING) { addressString += "." + (parentPlc?.GetConstantValue(entry.StringLength) ?? entry.StringLength.Value).ToString(); } var entryItems = new string[16] { entryPrefix + entry.Name, addressString, type, "1", "R/W", "100", string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, entry.Comment }; writer.WriteLine(string.Join(",", entryItems)); } } }
private static void CreateInternal(IEnumerable <DataBlock> blocks, string path, PortalPlc parentPlc) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (!FileHelpers.IsValidFilePath(path, ".csv")) { throw new ArgumentException(path + " is not a valid path.", nameof(path)); } try { using (var file = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { var writer = new StreamWriter(file); KepwareConfiguration.WriteHeaders(writer); foreach (var block in blocks) { if (block == null) { throw new ArgumentNullException(nameof(block)); } if (block.Children?.Count <= 0) { throw new ArgumentException("Block '" + block.Name + "' contains no data", nameof(block)); } KepwareConfiguration.ExportDataBlockToFile(block, writer, parentPlc); } writer.Flush(); } } catch (Exception e) { throw new SiemensException("Could not write Kepware configuration", e); } }
public static void Create(DataBlock block, string path, PortalPlc owningPlc) { KepwareConfiguration.CreateInternal(new[] { block }, path, owningPlc); }
public static void Create(DataBlock block, string path, PortalPlc parentPlc, AlarmworxSettings settings) { AlarmWorxConfiguration.Create(new[] { block }, path, parentPlc, settings); }