├── Directory.Build.targets ├── DirectoryBuildProps.png ├── versionize.json ├── docs └── images │ ├── Step7ProjectSubset.png │ ├── TestExplorerMenuEntry.png │ ├── StartdriveProjectSubset.png │ ├── TestExplorerMethodSelection.png │ └── TiaPortal.Openness.CodeSnippets.png ├── CHANGELOG.md ├── nuget.config ├── src ├── TiaPortal.Openness.CodeSnippets.Plain.Step7 │ ├── resources │ │ └── Step7.zap20 │ ├── LibrarySnippets.cs │ ├── HardwareCatalogSnippets.cs │ ├── Properties │ │ └── launchSettings.json │ ├── PLC │ │ ├── SafetySnippets.cs │ │ ├── SoftwareUnitsSnippets.cs │ │ ├── PlcAlarmTextListSnippets.cs │ │ ├── DataBlockSnippets.cs │ │ ├── TechnologyObjectSnippets.cs │ │ ├── TagTableSnippets.cs │ │ └── ProgramBlocks │ │ │ ├── Resources │ │ │ └── PLCBlocks │ │ │ │ ├── Block_1 │ │ │ │ ├── Block_2 │ │ │ │ ├── Block_3 │ │ │ │ ├── Block_4 │ │ │ │ ├── Block_5 │ │ │ │ └── Block_Merged │ │ │ └── ProgramBlockSnippets.cs │ ├── TiaPortal.Openness.CodeSnippets.Plain.Step7.csproj │ ├── NetworkSnippets.cs │ ├── TiaProcessSnippets.cs │ ├── SecuritySnippets.cs │ ├── TransferAreaSnippets.cs │ └── OnlineSnippets.cs ├── TiaPortal.Openness.CodeSnippets.Plain.Startdrive │ ├── resources │ │ └── Startdrive.zap20 │ ├── OnlineSnippets.cs │ ├── StartdriveSnippets.cs │ ├── TiaPortal.Openness.CodeSnippets.Plain.Startdrive.csproj │ ├── EncoderSnippets.cs │ ├── NetworkSnippets.cs │ ├── DriveObjectSnippets.cs │ ├── MotorSnippets.cs │ ├── ParameterSnippets.cs │ ├── HardwareCatalogSnippets.cs │ ├── SafetySnippets.cs │ ├── TechnologyObjectSnippets.cs │ ├── TelegramSnippets.cs │ └── HardwareSnippets.cs ├── TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc │ ├── resources │ │ └── DCC_Example.dcc │ ├── TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc.csproj │ └── DccSnippets.cs ├── TiaPortal.Openness.CodeSnippets.ViewModel │ └── TiaPortal.Openness.CodeSnippets.WithExtensions.ViewModel.csproj ├── Step7ProjectSubset.slnf ├── TiaPortal.Openness.CodeSnippets.WithExtensions.Setup │ ├── Setup │ │ ├── GlobalSetup.cs │ │ └── BaseClass.cs │ └── TiaPortal.Openness.CodeSnippets.WithExtensions.Setup.csproj ├── TiaPortal.Openness.CodeSnippets.Plain.Setup │ ├── Setup │ │ ├── GlobalSetup.cs │ │ ├── OpennessAssemblyResolverSnippet.cs │ │ └── BaseClass.cs │ └── TiaPortal.Openness.CodeSnippets.Plain.Setup.csproj ├── StartdriveProjectSubset.slnf ├── TiaPortal.Openness.CodeSnippets.WithExtensions.Step7 │ ├── OnlineSnippets.cs │ ├── TiaPortal.Openness.CodeSnippets.WithExtensions.Step7.csproj │ ├── PLC │ │ ├── PlcTagTableSnippets.cs │ │ └── ProgramBlockSnippets.cs │ └── Step7Snippets.cs ├── TiaPortal.Openness.CodeSnippets.sln.DotSettings ├── TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive │ ├── TechnologyObjectSnippets.cs │ ├── TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive.csproj │ ├── ParameterSnippets.cs │ ├── AttributePathSnippets.cs │ └── NetworkSnippets.cs └── TiaPortal.Openness.CodeSnippets.sln ├── SECURITY.md ├── Directory.Build.props ├── CODEOWNERS.md ├── CONTRIBUTING.md ├── README.md ├── CODE_OF_CONDUCT.md ├── LICENSE.md ├── .gitignore └── .editorconfig /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DirectoryBuildProps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/DirectoryBuildProps.png -------------------------------------------------------------------------------- /versionize.json: -------------------------------------------------------------------------------- 1 | { 2 | "changelogAll": true, 3 | "projectFile": "Directory.Build.props", 4 | "versionPrefix": "v" 5 | } -------------------------------------------------------------------------------- /docs/images/Step7ProjectSubset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/docs/images/Step7ProjectSubset.png -------------------------------------------------------------------------------- /docs/images/TestExplorerMenuEntry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/docs/images/TestExplorerMenuEntry.png -------------------------------------------------------------------------------- /docs/images/StartdriveProjectSubset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/docs/images/StartdriveProjectSubset.png -------------------------------------------------------------------------------- /docs/images/TestExplorerMethodSelection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/docs/images/TestExplorerMethodSelection.png -------------------------------------------------------------------------------- /docs/images/TiaPortal.Openness.CodeSnippets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/docs/images/TiaPortal.Openness.CodeSnippets.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [versionize](https://github.com/versionize/versionize) for commit guidelines. 4 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/resources/Step7.zap20: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/src/TiaPortal.Openness.CodeSnippets.Plain.Step7/resources/Step7.zap20 -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/resources/Startdrive.zap20: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/resources/Startdrive.zap20 -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc/resources/DCC_Example.dcc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siemens/tia-portal-openness-code-snippets/HEAD/src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc/resources/DCC_Example.dcc -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting Security Issues 2 | 3 | If you believe you have found a security vulnerability in Modular Application Creator use cases documentation, we encourage you to let us know right away via tech.team.motioncontrol@siemens.com. We will investigate all legitimate reports and do our best to quickly fix the problem. -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | preview 4 | false 5 | 20 6 | V$(TiaVersion) 7 | true 8 | 1.0.0 9 | 10 | -------------------------------------------------------------------------------- /CODEOWNERS.md: -------------------------------------------------------------------------------- 1 | # Lists the responsible maintainers of this repo. 2 | # 3 | # Each line is a file pattern followed by one or more owners. 4 | 5 | # These owners will be the default owners for everything in 6 | # the repo. Unless a later match takes precedence, 7 | # @global-owner1 and @global-owner2 will be requested for 8 | # review when someone opens a pull request. 9 | * @LukasDehmel-Siemens @ClaudiusR @dssAutomation @HamzaAdlane-Siemens @CSchmidtAutomation 10 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.ViewModel/TiaPortal.Openness.CodeSnippets.WithExtensions.ViewModel.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net48 5 | Latest 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Step7ProjectSubset.slnf: -------------------------------------------------------------------------------- 1 | { 2 | "solution": { 3 | "path": "TiaPortal.Openness.CodeSnippets.sln", 4 | "projects": [ 5 | "TiaPortal.Openness.CodeSnippets.Plain.Setup\\TiaPortal.Openness.CodeSnippets.Plain.Setup.csproj", 6 | "TiaPortal.Openness.CodeSnippets.Plain.Step7\\TiaPortal.Openness.CodeSnippets.Plain.Step7.csproj", 7 | "TiaPortal.Openness.CodeSnippets.WithExtensions.Setup\\TiaPortal.Openness.CodeSnippets.WithExtensions.Setup.csproj", 8 | "TiaPortal.Openness.CodeSnippets.WithExtensions.Step7\\TiaPortal.Openness.CodeSnippets.WithExtensions.Step7.csproj" 9 | ] 10 | } 11 | } -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Setup/Setup/GlobalSetup.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Collaboration.Net; 6 | 7 | //This should not be in a namespace 8 | [SetUpFixture] 9 | public class GlobalSetup 10 | { 11 | [OneTimeSetUp] 12 | public void GlobalOneTimeSetup() 13 | { 14 | Api.Global.Openness().Initialize(); 15 | } 16 | 17 | [OneTimeTearDown] 18 | public void GlobalOneTimeTearDown() 19 | { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Setup/Setup/GlobalSetup.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 6 | 7 | //This should not be in a namespace 8 | [SetUpFixture] 9 | public abstract class GlobalSetup 10 | { 11 | [OneTimeSetUp] 12 | public void GlobalOneTimeSetup() 13 | { 14 | AppDomain.CurrentDomain.AssemblyResolve += OpennessAssemblyResolverSnippet.ResolveSiemensEngineeringAssembly; 15 | } 16 | 17 | [OneTimeTearDown] 18 | public void GlobalOneTimeTearDown() 19 | { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Setup/TiaPortal.Openness.CodeSnippets.WithExtensions.Setup.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net48 5 | latest 6 | enable 7 | true 8 | true 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/StartdriveProjectSubset.slnf: -------------------------------------------------------------------------------- 1 | { 2 | "solution": { 3 | "path": "TiaPortal.Openness.CodeSnippets.sln", 4 | "projects": [ 5 | "TiaPortal.Openness.CodeSnippets.Plain.Setup\\TiaPortal.Openness.CodeSnippets.Plain.Setup.csproj", 6 | "TiaPortal.Openness.CodeSnippets.Plain.Startdrive\\TiaPortal.Openness.CodeSnippets.Plain.Startdrive.csproj", 7 | "TiaPortal.Openness.CodeSnippets.Plain.Step7\\TiaPortal.Openness.CodeSnippets.Plain.Step7.csproj", 8 | "TiaPortal.Openness.CodeSnippets.WithExtensions.Setup\\TiaPortal.Openness.CodeSnippets.WithExtensions.Setup.csproj", 9 | "TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive\\TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive.csproj", 10 | "TiaPortal.Openness.CodeSnippets.WithExtensions.Step7\\TiaPortal.Openness.CodeSnippets.WithExtensions.Step7.csproj" 11 | ] 12 | } 13 | } -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/LibrarySnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.Library; 6 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 7 | 8 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7; 9 | 10 | [TestFixture("Step7.zap20")] 11 | public class LibrarySnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 12 | { 13 | [Test] 14 | public void CreateGlobalLibrary() 15 | { 16 | DirectoryInfo destination = new(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); 17 | var globalLibrary = TiaPortalInstance.GlobalLibraries.Create(destination, "newLibrary"); 18 | Console.WriteLine($"Global library could be created: {globalLibrary != null}"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Step7/OnlineSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.Online; 6 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 7 | 8 | namespace TiaPortal.Openness.CodeSnippets.WithExtensions.Step7; 9 | 10 | [TestFixture("Step7.zap20")] 11 | public class OnlineSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 12 | { 13 | [Test] 14 | public void GoOfflineAllDevices() 15 | { 16 | var devices = Project.AllDevices(); 17 | var onlineProviders = devices 18 | .SelectMany(device => device.DeviceItems.Select(deviceItem => deviceItem.AsOnlineProvider())) 19 | .Where(provider => provider != null).ToList(); 20 | 21 | onlineProviders.Where(x => x.State == OnlineState.Online).ForEach(x => x.GoOffline()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/OnlineSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.Online; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 10 | 11 | [TestFixture("Startdrive.zap20")] 12 | public class OnlineSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void OnlineProvider_CurrentOnlineState() 16 | { 17 | var s120Device = Project.Devices.First(x => x.Name == "S120Democase"); 18 | 19 | var onlineProvider = s120Device.DeviceItems 20 | .First(x => x.Classification == DeviceItemClassifications.HM).GetService(); 21 | var currentState = onlineProvider.State; 22 | Console.WriteLine(currentState); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/HardwareCatalogSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 6 | 7 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7; 8 | 9 | [TestFixture("Step7.zap20")] 10 | public class HardwareCatalogSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 11 | { 12 | [Test] 13 | public void HardwareCatalog_AllEntries() 14 | { 15 | var hardwareCatalog = TiaPortalInstance.HardwareCatalog.Find(string.Empty); 16 | 17 | var catalogEntries = hardwareCatalog.ToList(); 18 | 19 | Console.WriteLine($"Total catalog entries: {catalogEntries.Count}"); 20 | 21 | foreach (var entry in catalogEntries) 22 | { 23 | Console.WriteLine($"TypeIdentifier: {entry.TypeIdentifier}, CatalogPath: {entry.CatalogPath}"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Setup/TiaPortal.Openness.CodeSnippets.Plain.Setup.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net48 4 | latest 5 | enable 6 | true 7 | $([MSBuild]::GetRegistryValueFromView(`HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\_InstalledSW\TIAP$(TiaVersion)\Global`, `Path`, '', RegistryView.Registry64, RegistryView.Registry32)) 8 | 9 | 10 | 11 | 12 | 13 | $(TiaPortalLocation)\PublicAPI\V$(TiaVersion)\Siemens.Engineering.dll 14 | False 15 | False 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True 3 | True 4 | True 5 | True 6 | True 7 | True 8 | True 9 | True -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/StartdriveSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 7 | 8 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 9 | 10 | [TestFixture("Startdrive.zap20")] 11 | public class StartdriveSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 12 | { 13 | [Test] 14 | public void ShowHwEditorDevice() 15 | { 16 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 17 | device.ShowInEditor(View.Device); 18 | } 19 | 20 | [Test] 21 | public void GetInstalledStartdriveVersion() 22 | { 23 | var tiaPortalProcess = TiaPortalInstance.GetCurrentProcess(); 24 | 25 | var installedStartdrive = tiaPortalProcess.InstalledSoftware.First(x => x.Name.Contains("Startdrive")); 26 | var startdriveVersion = installedStartdrive.Version; 27 | 28 | Console.WriteLine($"StartDrive Version: {startdriveVersion}"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Step7/TiaPortal.Openness.CodeSnippets.WithExtensions.Step7.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net48 4 | latest 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Always 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Siemens.Collaboration.Net.TiaPortal.Openness.CodeSnippets.Tests (local)": { 4 | "commandName": "Executable", 5 | "executablePath": "$(ExecutablePath)", 6 | "commandLineArgs": "$(StartArguments)" 7 | }, 8 | "Siemens.Collaboration.Net.TiaPortal.Openness.CodeSnippets.Tests (remote)": { 9 | "commandName": "Executable", 10 | "executablePath": "$(RemoteExecutablePath)", 11 | "commandLineArgs": "$(RemoteStartArguments)", 12 | "workingDirectory": "$(RemoteWorkingDirectoryPath)", 13 | "remoteDebugEnabled": true, 14 | "remoteDebugMachine": "$(RemoteDebugMachine)" 15 | }, 16 | "Siemens.Collaboration.Net.TiaPortal.Openness.CodeSnippets.Tests (remote admin)": { 17 | "commandName": "Executable", 18 | "executablePath": "$(RemoteExecutablePath)", 19 | "commandLineArgs": "$(RemoteStartArguments)", 20 | "workingDirectory": "$(RemoteWorkingDirectoryPath)", 21 | "remoteDebugEnabled": true, 22 | "remoteDebugMachine": "$(RemoteDebugMachineAdmin)" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive/TechnologyObjectSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.SW; 6 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 7 | 8 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 9 | 10 | [TestFixture("Startdrive.zap20")] 11 | public class TechnologyObjectSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 12 | { 13 | [Test] 14 | public void ConnectToToTest() 15 | { 16 | var s120 = Project.Devices.First(x => x.Name == "S120Democase"); 17 | var driveObject = s120.DriveAxes().First(x => x.Name == "BlueAxis").AsDriveObjectContainer() 18 | .DriveObject(); 19 | 20 | var plc = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 21 | var plcSoftware = plc.DeviceItems[1].Software() as PlcSoftware; 22 | 23 | 24 | var to = plcSoftware?.TechnologicalObjectGroup.AllTechnologicalInstanceDBs() 25 | .Single(x => x.Name == "PositioningAxis_blue"); 26 | 27 | driveObject.ConnectToTechnologyObject(to); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive/TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net48 4 | latest 5 | enable 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | Always 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/SafetySnippets.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Siemens.Engineering.HW; 3 | using Siemens.Engineering.Safety; 4 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 5 | 6 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7.PLC; 7 | 8 | [TestFixture("Step7.zap20")] 9 | public class SafetySnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 10 | { 11 | [Test] 12 | public void ReadoutSafetyAdministration() 13 | { 14 | // Find CPU 15 | var plc = Project.Devices 16 | .First(d => d.DeviceItems.Any(i => i.Classification == DeviceItemClassifications.CPU)); 17 | var cpu = plc.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.CPU); 18 | 19 | // Readout Safety Administration 20 | var safetyAdmin = cpu.GetService(); 21 | var runtimeGroup = safetyAdmin.RuntimeGroups.First(); 22 | 23 | var mainSafetyBlockName = runtimeGroup.GetAttribute("MainSafetyBlockName"); 24 | Console.WriteLine($"Could get block name: {mainSafetyBlockName != null}"); 25 | var mainSafetyDbName = runtimeGroup.GetAttribute("MainSafetyBlockIDbName"); 26 | Console.WriteLine($"Could get safety db name: {mainSafetyDbName != null}"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/SoftwareUnitsSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW.Features; 6 | using Siemens.Engineering.SW; 7 | using Siemens.Engineering.SW.Units; 8 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 9 | 10 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7.PLC; 11 | 12 | [TestFixture("Step7.zap20")] 13 | public class SoftwareUnitsSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 14 | { 15 | [Test] 16 | public void GetSoftwareUnits() 17 | { 18 | var deviceItem = Project.Devices.First(n => n.Name == "PLC_S120Democase").DeviceItems 19 | .First(n => n.Name.Contains("PLC")); 20 | var softwareContainer = deviceItem.GetService(); 21 | var plcSoftware = softwareContainer.Software as PlcSoftware; 22 | var plcUnitProvider = plcSoftware?.GetService(); 23 | var safetyUnits = plcUnitProvider?.UnitGroup.SafetyUnits; 24 | Console.WriteLine($"SafetyUnits found: {safetyUnits != null}"); 25 | var units = plcUnitProvider?.UnitGroup.Units; 26 | Console.WriteLine($"Units found: {units != null}"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/TiaPortal.Openness.CodeSnippets.Plain.Startdrive.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net48 5 | latest 6 | enable 7 | enable 8 | true 9 | $([MSBuild]::GetRegistryValueFromView(`HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\_InstalledSW\TIAP$(TiaVersion)\Global`, `Path`, '', RegistryView.Registry64, RegistryView.Registry32)) 10 | 11 | 12 | 13 | 14 | 15 | 16 | $(TiaPortalLocation)\PublicAPI\V$(TiaVersion)\Siemens.Engineering.dll 17 | False 18 | False 19 | 20 | 21 | Always 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/TiaPortal.Openness.CodeSnippets.Plain.Step7.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net48 5 | latest 6 | enable 7 | enable 8 | true 9 | $([MSBuild]::GetRegistryValueFromView(`HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\_InstalledSW\TIAP$(TiaVersion)\Global`, `Path`, '', RegistryView.Registry64, RegistryView.Registry32)) 10 | 11 | 12 | 13 | 14 | 15 | 16 | $(TiaPortalLocation)\PublicAPI\V$(TiaVersion)\Siemens.Engineering.dll 17 | False 18 | 19 | 20 | 21 | 22 | 23 | 24 | Always 25 | 26 | 27 | 28 | 29 | Always 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc/TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net48 5 | latest 6 | enable 7 | enable 8 | true 9 | $([MSBuild]::GetRegistryValueFromView(`HKEY_LOCAL_MACHINE\SOFTWARE\Siemens\Automation\_InstalledSW\TIAP$(TiaVersion)\Global`, `Path`, '', RegistryView.Registry64, RegistryView.Registry32)) 10 | 11 | 12 | 13 | Always 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | $(TiaPortalLocation)\PublicAPI\V$(TiaVersion)\Siemens.Engineering.dll 22 | False 23 | False 24 | 25 | 26 | Always 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/EncoderSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.MC.Drives; 6 | using Siemens.Engineering.MC.Drives.DFI; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 10 | 11 | [TestFixture("Startdrive.zap20")] 12 | public class EncoderSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | //Function for projecting third party encoder configuration 15 | [Test] 16 | public void ProjectEncoderConfiguration() 17 | { 18 | var drive = Project.Devices.First(x => x.Name == "S120Democase"); 19 | 20 | var driveObject = drive.DeviceItems.Single(x => x.Name == "AxisWith3rdPartyMotor") 21 | .GetService() 22 | .DriveObjects.First(); 23 | 24 | var hardwareProjection = driveObject.GetService().HardwareProjection; 25 | 26 | var encoderConfig = hardwareProjection.GetCurrentEncoderConfiguration(0); 27 | 28 | encoderConfig.RequiredConfigurationEntries.ToList().ForEach(ce => 29 | { 30 | ce.Value = ce.Name switch 31 | { 32 | "p404.20" => true, 33 | "p404.21" => false, 34 | "p427" => 0, 35 | "p429.0" or "p429.2" or "p429.6" => true, 36 | "p428" or "p433" or "p434" or "p435" or "p436" or "p446" or "p447" or "p448" or "p449" => 30, 37 | _ => ce.Value 38 | }; 39 | }); 40 | hardwareProjection.ProjectEncoderConfiguration(encoderConfig, 1); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive/ParameterSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 6 | 7 | namespace TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive; 8 | 9 | [TestFixture("Startdrive.zap20")] 10 | public class ParameterSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 11 | { 12 | [Test] 13 | public void GetParametersWithExtension() 14 | { 15 | var device = Project.AllStartdriveDevices().First(x => x.Name == "S120Democase"); 16 | var driveAxes = device.DriveAxes(); 17 | var parameters = driveAxes.First(x => x.Name.Contains("Red")).AsDriveObjectContainer().Parameters(); 18 | 19 | Console.WriteLine("First 10 parameters:"); 20 | Console.WriteLine(string.Join("\n", parameters.Take(10).Select(p => $"{p.Name}"))); 21 | } 22 | 23 | [Test] 24 | public void GetParameterValues_InParallel_WithOptions() 25 | { 26 | var drive = Project.AllStartdriveDevices().First(x => x.Name == "S120Democase"); 27 | var driveAxis = drive.DriveAxes().First(); 28 | 29 | var parameterComposition = driveAxis.AsDriveObjectContainer().Parameters(); 30 | var parameters = new List<(string name, object value)>(); 31 | 32 | var options = new ParallelOptions { MaxDegreeOfParallelism = 10 }; 33 | 34 | Parallel.ForEach(parameterComposition, options, parameter => 35 | { 36 | parameters.Add((parameter.Name, parameter.Value)); 37 | }); 38 | 39 | Console.WriteLine("First 10 parameters:"); 40 | Console.WriteLine(string.Join("\n", parameters.Take(10).Select(p => $"{p.name}"))); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Setup/Setup/BaseClass.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering; 6 | 7 | namespace TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 8 | 9 | [SetUpFixture] 10 | public abstract class BaseClass(string tiaArchiveName) : GlobalSetup 11 | { 12 | private DirectoryInfo _tempProjectDirectory; 13 | 14 | public Siemens.Engineering.TiaPortal TiaPortalInstance { get; private set; } 15 | 16 | public Project Project { get; private set; } 17 | 18 | [OneTimeSetUp] 19 | public void OneTimeSetup() 20 | { 21 | var tiaProcesses = Siemens.Engineering.TiaPortal.GetProcesses(); 22 | foreach (var tiaPortalProcess in tiaProcesses) 23 | { 24 | TiaPortalInstance = tiaPortalProcess.Attach(); 25 | foreach (var project in TiaPortalInstance.Projects) 26 | { 27 | if (project.Name == tiaArchiveName.Remove(tiaArchiveName.IndexOf(".zap", StringComparison.Ordinal))) 28 | { 29 | Project = project; 30 | return; 31 | } 32 | } 33 | } 34 | 35 | TiaPortalInstance = new Siemens.Engineering.TiaPortal(TiaPortalMode.WithUserInterface); 36 | var resourceDict = Path.Combine(TestContext.CurrentContext.TestDirectory, "resources"); 37 | var myStep7ProjectArchivePath = Path.Combine(resourceDict, tiaArchiveName); 38 | FileInfo sourcePath = new(myStep7ProjectArchivePath); 39 | 40 | _tempProjectDirectory = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); 41 | Project = TiaPortalInstance.Projects.Retrieve(sourcePath, _tempProjectDirectory); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/NetworkSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.HW.Features; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 10 | 11 | [TestFixture("Startdrive.zap20")] 12 | public class NetworkSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void ProfinetConfigurations() 16 | { 17 | var g120 = 18 | TiaPortalInstance.Projects.First().Devices.First(x => x.Name == "SINAMICS G120"); 19 | 20 | var headModule = g120.DeviceItems.First(x => x.Classification == DeviceItemClassifications.HM); 21 | var profinetInterface = headModule.DeviceItems[0]; 22 | var networkInterface = profinetInterface.GetService(); 23 | var node = networkInterface.Nodes.First(); 24 | 25 | //Set IP Address 26 | node.SetAttribute("Address", "192.168.0.2"); 27 | 28 | //Set subnet mask 29 | node.SetAttribute("SubnetMask", "255.255.0.0"); 30 | 31 | //Set PnDeviceName 32 | node.SetAttribute("PnDeviceNameAutoGeneration", false); 33 | node.SetAttribute("PnDeviceName", "name"); 34 | } 35 | 36 | [Test] 37 | public void GetProfinetInterface_Drive() 38 | { 39 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 40 | 41 | var headModule = device.DeviceItems.First(x => x.Classification == DeviceItemClassifications.HM); 42 | var profinetInterface = headModule.DeviceItems.FirstOrDefault(); 43 | 44 | Console.WriteLine($"Profinet Interface found: {profinetInterface != null}"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Step7/PLC/PlcTagTableSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.HW.Features; 7 | using Siemens.Engineering.SW; 8 | using Siemens.Engineering.SW.Tags; 9 | using Siemens.Engineering.SW.Units; 10 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 11 | 12 | namespace TiaPortal.Openness.CodeSnippets.WithExtensions.Step7.PLC; 13 | 14 | [TestFixture("Step7.zap20")] 15 | public class PlcTagTableSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 16 | { 17 | [Test] 18 | public void GetAllPlcTags() 19 | { 20 | var device = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 21 | var allPlcTags = GetAllPlcTags(device); 22 | Console.WriteLine(string.Join("\n"), allPlcTags.Select(l => $"{l.Name}")); 23 | } 24 | 25 | private static List GetAllPlcTags(Device plcDevice) 26 | { 27 | var allTagTables = GetAllPlcTagTables(plcDevice); 28 | return allTagTables.SelectMany(x => x.Tags).ToList(); 29 | } 30 | 31 | private static List GetAllPlcTagTables(Device plcDevice) 32 | { 33 | if (plcDevice.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.CPU) 34 | .GetService().Software is not PlcSoftware software) 35 | { 36 | throw new InvalidOperationException("Device does not contain any software instance (null)."); 37 | } 38 | 39 | var tagTables = software.TagTableGroup.AllTagTables(); 40 | 41 | var units = software.GetService().UnitGroup.Units; 42 | var unitTagTables = units.SelectMany(x => x.TagTableGroup.AllTagTables()); 43 | var allTagTables = tagTables.Concat(unitTagTables); 44 | return allTagTables.ToList(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/DriveObjectSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.MC.Drives; 6 | using Siemens.Engineering.MC.Drives.DFI; 7 | using Siemens.Engineering.MC.Drives.Enums; 8 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 9 | 10 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 11 | 12 | [TestFixture("Startdrive.zap20")] 13 | public class DriveObjectSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 14 | { 15 | [Test] 16 | public void DriveObjectType() 17 | { 18 | var s120 = Project.Devices.First(x => x.Name == "S120Democase"); 19 | 20 | var driveFunctionInterface = s120.DeviceItems[3].GetService().DriveObjects.First() 21 | .GetService(); 22 | 23 | var driveObjectTypeHandler = driveFunctionInterface.DriveObjectFunctions.DriveObjectTypeHandler; 24 | var currentType = driveObjectTypeHandler.CurrentDriveObjectType; 25 | 26 | var possibleDriveObjectTypesList = driveObjectTypeHandler.PossibleDriveObjectTypes.Select(x => x.Name).ToList(); 27 | var typeFromPossibleTypes = possibleDriveObjectTypesList.Single(x => x == currentType.Name); 28 | var typeIndex = possibleDriveObjectTypesList.IndexOf(typeFromPossibleTypes); 29 | Console.WriteLine(typeIndex); 30 | } 31 | 32 | [Test] 33 | public void DeactivateDriveObjectTest() 34 | { 35 | var drive = Project.Devices.First(x => x.Name == "S120Democase"); 36 | 37 | var driveObject = drive.DeviceItems.Single(x => x.Name == "BlueAxis").GetService() 38 | .DriveObjects.First(); 39 | 40 | var dfi = driveObject.GetService(); 41 | dfi.DriveObjectFunctions.DriveObjectActivation.ChangeActivationState(DriveObjectActivationState.Deactivate); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/MotorSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.MC.Drives; 6 | using Siemens.Engineering.MC.Drives.DFI; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 10 | 11 | [TestFixture("Startdrive.zap20")] 12 | public class MotorSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | //Function for projecting third party motor configuration 15 | [Test] 16 | public void ProjectMotorConfiguration() 17 | { 18 | var drive = Project.Devices.First(x => x.Name == "S120Democase"); 19 | 20 | var driveObject = drive.DeviceItems.Single(n => n.Name == "AxisWith3rdPartyMotor") 21 | .GetService() 22 | .DriveObjects.First(); 23 | 24 | var hardwareProjection = driveObject.GetService().HardwareProjection; 25 | var motorConfiguration = hardwareProjection.GetCurrentMotorConfiguration(0); 26 | 27 | motorConfiguration.SetEquivalentCircuitDiagramData(false); 28 | 29 | motorConfiguration.RequiredConfigurationEntries.ToList().ForEach(ce => 30 | { 31 | ce.Value = ce.Number switch 32 | { 33 | 305 => 1.0, 34 | 311 => 1.0, 35 | 314 => 1.0, 36 | 316 => 1.0, 37 | 322 => 1.0, 38 | 323 => 1.0, 39 | _ => ce.Value 40 | }; 41 | }); 42 | motorConfiguration.OptionalConfigurationEntries.ToList().ForEach(ce => 43 | { 44 | ce.Value = ce.Number switch 45 | { 46 | 317 => 1.0, 47 | 348 => 1.1, 48 | _ => ce.Value 49 | }; 50 | }); 51 | 52 | hardwareProjection.ProjectMotorConfiguration(motorConfiguration, 0); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Step7/Step7Snippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Collaboration.Net; 6 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 7 | using Mode = Siemens.Collaboration.Net.TiaPortal.Openness.Resolver.Mode; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.WithExtensions.Step7; 10 | 11 | [TestFixture("Step7.zap20")] 12 | public class Step7Snippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void GetAllInstalledTiaVersions() 16 | { 17 | var apiFolders = Api.Global.Openness().GetPublicApiFoldersFromRegistry(); 18 | var installedVersions = apiFolders 19 | .Select(folder => 20 | { 21 | var parentName = folder?.Parent?.Name.ToString(); 22 | if (string.IsNullOrWhiteSpace(parentName)) 23 | { 24 | return null; 25 | } 26 | 27 | var nameParts = parentName?.Split(' '); 28 | return nameParts is { Length: > 0 } ? nameParts.Last() : null; 29 | }) 30 | .Where(version => !string.IsNullOrWhiteSpace(version)) 31 | .Distinct() 32 | .ToList(); 33 | 34 | // Optionally output for verification 35 | installedVersions.ForEach(version => Console.WriteLine($"Installed TIA Version: {version}")); 36 | } 37 | 38 | [Test] 39 | public void GetTiaPortalProcesses() 40 | { 41 | const int SupportedVersion = 18; 42 | var tiaProcesses = Api.Global.Openness() 43 | .GetTiaPortalProcesses(Mode.WithUserInterface) 44 | .Where(p => p.Version.Major >= SupportedVersion).ToList(); 45 | 46 | //Here you need a user interaction to choose from the processes 47 | var chosenProcess = tiaProcesses.First(); 48 | 49 | Api.Global.Openness().Initialize(chosenProcess.ProcessId); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Setup/Setup/OpennessAssemblyResolverSnippet.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using System.Reflection; 5 | using Microsoft.Win32; 6 | 7 | namespace TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | public class OpennessAssemblyResolverSnippet 10 | { 11 | private const string SiemensEngineeringDllName = "Siemens.Engineering"; 12 | private const string SubKeyName = @"SOFTWARE\Siemens\Automation\Openness"; 13 | 14 | public static Assembly ResolveSiemensEngineeringAssembly(object sender, ResolveEventArgs args) 15 | { 16 | var assemblyName = new AssemblyName(args.Name); 17 | if (assemblyName.Name != SiemensEngineeringDllName) 18 | { 19 | return null; 20 | } 21 | 22 | var assemblyVersion = 23 | args.Name.Split(',').FirstOrDefault(x => x.Contains("Version")).Split('=')[1].Split('.')[0]; 24 | 25 | 26 | using var regBaseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, 27 | RegistryView.Registry64); 28 | using var opennessBaseKey = regBaseKey.OpenSubKey(SubKeyName); 29 | using var registryKeyLatestTiaVersion = opennessBaseKey? 30 | .OpenSubKey(opennessBaseKey.GetSubKeyNames().FirstOrDefault(x => x.Contains(assemblyVersion))); 31 | var requestedVersionOfAssembly = assemblyName.Version.ToString(); 32 | 33 | using var assemblyVersionSubKey = registryKeyLatestTiaVersion 34 | ?.OpenSubKey("PublicAPI") 35 | ?.OpenSubKey(requestedVersionOfAssembly); 36 | var siemensEngineeringAssemblyPath = assemblyVersionSubKey? 37 | .GetValue(SiemensEngineeringDllName).ToString(); 38 | if (siemensEngineeringAssemblyPath == null 39 | || !File.Exists(siemensEngineeringAssemblyPath)) 40 | { 41 | return null; 42 | } 43 | 44 | var assembly = Assembly.LoadFrom(siemensEngineeringAssemblyPath); 45 | return assembly; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Step7/PLC/ProgramBlockSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.SW.Blocks; 6 | using Siemens.Engineering.SW.ExternalSources; 7 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.WithExtensions.Step7.PLC; 10 | 11 | [TestFixture("Step7.zap20")] 12 | public class ProgramBlockSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void SclExportTest() 16 | { 17 | var software = Project.Devices.First(x => x.Name.Equals("PLC_S120Democase")).AsPlc(); 18 | 19 | FileInfo fileInfo = new(Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid().ToString()}.scl")); 20 | 21 | var exportableBlocks = software.BlockGroup.AllFBs().Where(b => 22 | !b.IsKnowHowProtected && b.ProgrammingLanguage is ProgrammingLanguage.SCL or ProgrammingLanguage.STL); 23 | 24 | software.ExternalSourceGroup.GenerateSource(exportableBlocks, fileInfo, GenerateOptions.None); 25 | 26 | Console.WriteLine($"File exists: {fileInfo.Exists}"); 27 | fileInfo.Delete(); 28 | } 29 | 30 | [Test] 31 | public void GetAllProgramBlocksOnFolder() 32 | { 33 | var software = Project.Devices.First(x => x.Name.Equals("PLC_S120Democase")).AsPlc(); 34 | 35 | var allProgramBlocks = software.BlockGroup.AllBlocks().ToList(); 36 | 37 | foreach (var programBlock in allProgramBlocks) 38 | { 39 | Console.WriteLine($"Found program block: {programBlock.Name}"); 40 | } 41 | } 42 | 43 | 44 | [Test] 45 | public void GetAllUserProgramBlocksOnFolder() 46 | { 47 | var software = Project.Devices.First(x => x.Name.Equals("PLC_S120Democase")).AsPlc(); 48 | 49 | var allUserProgramBlocks = software.BlockGroup.AllUserBlocks(); 50 | 51 | foreach (var programBlock in allUserProgramBlocks) 52 | { 53 | Console.WriteLine($"Found program block: {programBlock.Name}"); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Setup/Setup/BaseClass.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering; 6 | 7 | namespace TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | [SetUpFixture] 10 | public abstract class BaseClass(string tiaArchiveName) : GlobalSetup 11 | { 12 | private DirectoryInfo _tempProjectDirectory; 13 | 14 | public Siemens.Engineering.TiaPortal TiaPortalInstance { get; private set; } 15 | 16 | public Project Project { get; private set; } 17 | 18 | [OneTimeSetUp] 19 | public void OneTimeSetup() 20 | { 21 | var tiaProcesses = Siemens.Engineering.TiaPortal.GetProcesses(); 22 | if (tiaProcesses.Count > 0) 23 | { 24 | foreach (var tiaPortalProcess in tiaProcesses) 25 | { 26 | TiaPortalInstance = tiaPortalProcess.Attach(); 27 | foreach (var project in TiaPortalInstance.Projects) 28 | { 29 | if (project.Name != tiaArchiveName.Remove(tiaArchiveName.IndexOf(".zap", StringComparison.Ordinal))) 30 | { 31 | continue; 32 | } 33 | 34 | Project = project; 35 | return; 36 | } 37 | } 38 | } 39 | 40 | TiaPortalInstance = new Siemens.Engineering.TiaPortal(TiaPortalMode.WithUserInterface); 41 | var resourceDict = Path.Combine(TestContext.CurrentContext.TestDirectory, "resources"); 42 | var myStep7ProjectArchivePath = Path.Combine(resourceDict, tiaArchiveName); 43 | FileInfo sourcePath = new(myStep7ProjectArchivePath); 44 | 45 | _tempProjectDirectory = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); 46 | Project = TiaPortalInstance.Projects.Retrieve(sourcePath, _tempProjectDirectory); 47 | } 48 | 49 | [OneTimeTearDown] 50 | public void OneTimeTearDown() 51 | { 52 | //Project?.Close(); 53 | //Process.GetProcessById(TiaPortalInstance.GetCurrentProcess().Id).Kill(); 54 | //_tempProjectDirectory.Delete(true); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We welcome contributions in several forms, e.g. 4 | 5 | * Sponsoring 6 | * Documenting 7 | * Testing 8 | * Coding 9 | * etc. 10 | 11 | Please check the [Issues](https://github.com/siemens/tia-portal-openness-code-snippets/issues) and look for 12 | unassigned ones or create a new one. 13 | 14 | Working together in an open and welcoming environment is the foundation of our 15 | success, so please respect our [Code of Conduct](CODE_OF_CONDUCT.md). 16 | 17 | You can contribute even if you are new to the platform. The article below lays out ways you can make meaningful 18 | contributions regardless of your skill levels. It remains highly relevant and also applies to our Inner Source approach: 19 | 20 | [14 Ways to Contribute to Open Source without Being a Programming Genius or a Rock Star](https://web.archive.org/web/20231130050456/https://smartbear.com/blog/14-ways-to-contribute-to-open-source-without-being/). 21 | 22 | ## Guidelines 23 | 24 | ### Workflow 25 | 26 | We use the 27 | [Feature Branch Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow) 28 | and review all changes we merge to the main branch. 29 | 30 | We appreciate any contributions, so please use the [Forking Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow) 31 | and send us [Merge Requests](https://docs.gitlab.com/17.10/user/project/merge_requests/)! 32 | 33 | ### Commit Message 34 | 35 | Commit messages shall follow the conventions defined by [conventionalcommits](https://www.conventionalcommits.org/en/v1.0.0/#summary), for example: 36 | 37 | * `docs(security): add dockle security chapter` 38 | * `fix(theme): properly size and position hero img` 39 | * `style(markdown): run markdownlint auto-fix with latest version` 40 | 41 | If you accidentally pushed a commit with a malformed message you have to [reword the commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/changing-a-commit-message). 42 | 43 | #### What To Use as Scope 44 | 45 | In most cases the changed component is a good choice as scope 46 | e.g. if the change is done in the windows manual, the scope should be *windows*. 47 | 48 | For documentation changes the section that was changed makes a good scope name 49 | e.g. use *FAQ* if you changed that section. -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/ParameterSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.MC.Drives; 6 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 7 | 8 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 9 | 10 | [TestFixture("Startdrive.zap20")] 11 | public class ParameterSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 12 | { 13 | [Test] 14 | public void WritingBiCoParameters() 15 | { 16 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 17 | 18 | var redAxis = device.DeviceItems.Single(n => n.Name == "RedAxis"); 19 | var controlUnit = device.DeviceItems[0]; 20 | 21 | var bicoParameter = redAxis.GetService().DriveObjects.First().Parameters 22 | .Find(840, 0); 23 | var parameterBits = controlUnit.GetService().DriveObjects.First().Parameters 24 | .Find(2139, -1).Bits; 25 | 26 | //Code to find parameter 2139.7 27 | //Code that will get the wrong parameter: 28 | var incorrectParameter = parameterBits[7]; 29 | Console.WriteLine( 30 | $"Lookup with index 'parameterBits[7]' results in incorrect parameter: {incorrectParameter.Name}"); 31 | 32 | //Better: 33 | var connectedParameter = parameterBits.First(x => x.Name.Substring(x.Name.IndexOf('.') + 1) == "7"); 34 | Console.WriteLine($"Lookup by name results in parameter as expected: {connectedParameter.Name}"); 35 | 36 | bicoParameter.Value = connectedParameter; 37 | } 38 | 39 | [Test] 40 | public void GetIndexParameter() 41 | { 42 | var drive = Project.Devices.First(x => x.Name == "S120Democase"); 43 | var driveObject = drive.DeviceItems.First().GetService().DriveObjects.First(); 44 | 45 | var parameters = driveObject.Parameters; 46 | 47 | var parameterViaIndexAccess = parameters[100]; 48 | Console.WriteLine(parameterViaIndexAccess.Name); 49 | var parameterViaStringAccess = parameters.Find("r945[2]"); 50 | Console.WriteLine($"{parameterViaStringAccess.Name}={parameterViaStringAccess.Value}"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/PlcAlarmTextListSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.HW.Features; 7 | using Siemens.Engineering.Library; 8 | using Siemens.Engineering.SW; 9 | using Siemens.Engineering.SW.Alarm; 10 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 11 | 12 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7.PLC; 13 | 14 | [TestFixture("Step7.zap20")] 15 | public class PlcAlarmTextListSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 16 | { 17 | [Test] 18 | public void GetAlarmTextProvider() 19 | { 20 | var softwareContainer = TiaPortalInstance.Projects.First().Devices 21 | .First(x => x.TypeIdentifier.Equals("System:Device.S71500")) 22 | .DeviceItems 23 | .First(x => x.Classification.Equals(DeviceItemClassifications.CPU)).GetService(); 24 | 25 | var software = softwareContainer.Software as PlcSoftware; 26 | if (software == null) 27 | { 28 | Console.WriteLine("PlcSoftware not found"); 29 | } 30 | 31 | var alarmTextProvider = software?.GetService(); 32 | Console.WriteLine($"PlcAlarmTextProvider found: {alarmTextProvider != null}"); 33 | } 34 | 35 | [Test] 36 | public void AddPlcAlarmTextListToGlobalLibrary() 37 | { 38 | DirectoryInfo destination = new(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); 39 | 40 | var globalLibrary = TiaPortalInstance.GlobalLibraries.Create(destination, "newLibrary"); 41 | var plcSoftware = 42 | Project.Devices.First(x => x.Name == "PLC_S120Democase").DeviceItems 43 | .Single(x => x.Classification == DeviceItemClassifications.CPU).GetService() 44 | .Software as PlcSoftware; 45 | 46 | //only user text lists could be added (PlcAlarmSystemTextlists not working!) 47 | var alarmTextList = 48 | plcSoftware.PlcAlarmTextlistGroup.PlcAlarmUserTextlists.FirstOrDefault(x => 49 | x.Name == "USER_1"); 50 | var copy = globalLibrary.MasterCopyFolder.MasterCopies.Create(alarmTextList); 51 | 52 | Console.WriteLine($"Could create a copy: {copy != null}"); 53 | 54 | globalLibrary.Close(); 55 | destination.Delete(true); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/DataBlockSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.CrossReference; 6 | using Siemens.Engineering.HW.Features; 7 | using Siemens.Engineering.SW; 8 | using Siemens.Engineering.SW.Blocks; 9 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 10 | 11 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7.PLC; 12 | 13 | [TestFixture("Step7.zap20")] 14 | public class DataBlockSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 15 | { 16 | [Test] 17 | public void GetCrossReferencesForDb() 18 | { 19 | var plcDevice = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 20 | 21 | var plcSoftware = plcDevice.DeviceItems[1].GetService().Software as PlcSoftware; 22 | 23 | var db = plcSoftware?.BlockGroup.Blocks.First(x => x.Name == "Axis_red_DB"); 24 | var crossReferenceService = db?.GetService(); 25 | var crossReferences = 26 | crossReferenceService?.GetCrossReferences(CrossReferenceFilter.AllObjects).Sources.ToList(); 27 | 28 | 29 | if (crossReferences != null) 30 | { 31 | Console.WriteLine(string.Join("\n", crossReferences.Select(c => $"{c.Name}"))); 32 | } 33 | } 34 | 35 | [Test] 36 | public void GetDbInterfaceMembers() 37 | { 38 | var plcDevice = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 39 | if (plcDevice.DeviceItems[1].GetService().Software is not PlcSoftware plcSoftware) 40 | { 41 | throw new InvalidOperationException("The device does not contain a software container"); 42 | } 43 | 44 | if (plcSoftware.BlockGroup.Blocks.First(x => x.Name == "Axis_red_DB") is not InstanceDB instanceDb) 45 | { 46 | throw new InvalidOperationException("Axis_red_DB is not a InstanceDB"); 47 | } 48 | 49 | if (plcSoftware.BlockGroup.Blocks.First(x => x.Name == "GlobalBlock") is not GlobalDB globalDb) 50 | { 51 | throw new InvalidOperationException("GlobalBlock is not a GlobalDB"); 52 | } 53 | 54 | var instanceMembers = instanceDb.Interface.Members; 55 | Console.WriteLine(string.Join("\n", instanceMembers.Select(m => m.Name))); 56 | var globalMembers = globalDb.Interface.Members; 57 | Console.WriteLine(string.Join("\n", globalMembers.Select(m => m.Name))); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc/DccSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.MC.Drives; 6 | using Siemens.Engineering.MC.Drives.Dcc; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.StartDrive.Dcc; 10 | 11 | [TestFixture("Startdrive.zap20")] 12 | public class DccSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void GetInstalledDccVersion() 16 | { 17 | var tiaPortalProcess = TiaPortalInstance.GetCurrentProcess(); 18 | 19 | var installedStartdrive = tiaPortalProcess.InstalledSoftware.First(x => x.Name.Contains("Startdrive")); 20 | var installedDcc = installedStartdrive.Options.First(x => x.Name.Contains("DCC")); 21 | 22 | var dccVersion = installedDcc.Version; 23 | Console.WriteLine($"DCC Version: {dccVersion}"); 24 | var majorVersion = int.Parse(dccVersion.Substring(1, 2)); 25 | Console.WriteLine($"DCC Major Version: {majorVersion}"); 26 | 27 | const string UpdateString = "Update"; 28 | if (!dccVersion.Contains(UpdateString)) 29 | { 30 | return; 31 | } 32 | 33 | var index = dccVersion.IndexOf(UpdateString, StringComparison.Ordinal) + UpdateString.Length; 34 | var dccUpdateVersion = dccVersion.Substring(index, 2); 35 | Console.WriteLine($"DCC Update Version: {dccUpdateVersion}"); 36 | } 37 | 38 | [Test] 39 | public void DccImportExport() 40 | { 41 | var baseDirectory = AppDomain.CurrentDomain.BaseDirectory; 42 | var importDccPath = 43 | new FileInfo(Path.Combine(baseDirectory, "resources", "DCC_Example.dcc")); 44 | var exportDccPath = 45 | new FileInfo(Path.Combine(baseDirectory, "resources", 46 | "DCC_Example_exported.dcc")); 47 | var device = Project.Devices.First(x => x.Name.Contains("S120Democase")); 48 | 49 | //First we import a specific chart 50 | var dccCharts = device.DeviceItems.First(x => x.Name.Contains("BlueAxis")).GetService() 51 | .DriveObjects 52 | .First().GetService().Charts; 53 | dccCharts.Import(importDccPath.ToString(), DccImportOptions.RenameOnConflict); 54 | 55 | //Export the charts 56 | Console.WriteLine(string.Join("\n", dccCharts.Select(n => n.Name))); 57 | dccCharts.Single(c => c.Name == "DCC_Example").Export(exportDccPath.FullName); 58 | 59 | Console.WriteLine($"Exported dcc plan exists: {exportDccPath.Exists}"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/TechnologyObjectSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.HW.Features; 7 | using Siemens.Engineering.SW; 8 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 9 | 10 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7.PLC; 11 | 12 | [TestFixture("Step7.zap20")] 13 | public class TechnologyObjectSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 14 | { 15 | [Test] 16 | public void CreateTechnologyObject() 17 | { 18 | var plcDevice = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 19 | var plcSoftware = plcDevice.DeviceItems[1].GetService().Software as PlcSoftware; 20 | 21 | const string NameOfTo = "ABC"; 22 | const string TypeOfTo = "TO_SpeedAxis"; 23 | Version versionOfTo = new(6, 0); 24 | 25 | var toCreated = plcSoftware?.TechnologicalObjectGroup.TechnologicalObjects.Create(NameOfTo, 26 | TypeOfTo, 27 | versionOfTo); 28 | 29 | Console.WriteLine($"To created: {toCreated != null}"); 30 | } 31 | 32 | [Test] 33 | public void SetTechnologyObjectHwLimits() 34 | { 35 | var plc = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 36 | var cpu = plc.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.CPU); 37 | 38 | var plcSoftware = cpu.GetService().Software as PlcSoftware; 39 | var to = 40 | plcSoftware?.TechnologicalObjectGroup.TechnologicalObjects.First(x => x.Name == "PositioningAxis_blue"); 41 | 42 | if (to == null) 43 | { 44 | Console.WriteLine("to could not be found"); 45 | return; 46 | } 47 | 48 | to.Parameters.Find("PositionLimits_HW.Active").Value = true; 49 | 50 | var connectedTag = plcSoftware?.TagTableGroup.TagTables.First(x => x.Name.ToLower().Contains("default")).Tags 51 | .Find("test"); 52 | 53 | to.Parameters.Find("_PositionLimits_HW.MinSwitchAddress").Value = connectedTag; 54 | } 55 | 56 | [Test] 57 | public void WriteParametersInTechnologyObject() 58 | { 59 | var plcDevice = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 60 | 61 | var plcSoftware = plcDevice.DeviceItems[1].GetService().Software as PlcSoftware; 62 | 63 | var technologyObject = 64 | plcSoftware?.TechnologicalObjectGroup.TechnologicalObjects.First(x => x.Name == "PositioningAxis_blue"); 65 | 66 | if (technologyObject == null) 67 | { 68 | Console.WriteLine("To not found"); 69 | return; 70 | } 71 | 72 | technologyObject.Parameters.Find("Actor.InverseDirection").Value = true; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/HardwareCatalogSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using System.Text; 5 | using NUnit.Framework; 6 | using Siemens.Engineering.HW; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7; 10 | 11 | [TestFixture("Startdrive.zap20")] 12 | public class HardwareCatalogSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void HardwareCatalog_AllEntries() 16 | { 17 | var hardwareCatalog = TiaPortalInstance.HardwareCatalog.Find(string.Empty); 18 | 19 | var output = new StringBuilder(); 20 | output.AppendLine($"Total catalog entries: {hardwareCatalog.Count}"); 21 | 22 | var entries = string.Join(Environment.NewLine, 23 | hardwareCatalog.Select(entry => 24 | $"TypeIdentifier: {entry.TypeIdentifier}, CatalogPath: {entry.CatalogPath}")); 25 | 26 | output.AppendLine(entries); 27 | Console.WriteLine(output.ToString()); 28 | } 29 | 30 | [Test] 31 | public void HardwareCatalog_AllEntriesForS120() 32 | { 33 | var hardwareCatalog = TiaPortalInstance.HardwareCatalog.Find("S120"); 34 | 35 | var catalogEntries = hardwareCatalog.ToList(); 36 | 37 | Console.WriteLine($"Total S120 catalog entries: {catalogEntries.Count}"); 38 | 39 | foreach (var entry in catalogEntries) 40 | { 41 | Console.WriteLine($"TypeIdentifier: {entry.TypeIdentifier}, CatalogPath: {entry.CatalogPath}"); 42 | } 43 | } 44 | 45 | [Test] 46 | public void HardwareCatalog_DriveCliqMotorTypeIdentifier() 47 | { 48 | var hardwareCatalog = TiaPortalInstance.HardwareCatalog; 49 | 50 | var motorEntries = hardwareCatalog.Find("motors") 51 | .Where(x => x.CatalogPath != null && x.CatalogPath.ToLower().Contains("cliq")) 52 | .ToList(); 53 | 54 | if (motorEntries.Count == 0) 55 | { 56 | Console.WriteLine("No DriveCliq motor entries found in the hardware catalog."); 57 | } 58 | 59 | foreach (var entry in motorEntries) 60 | { 61 | Console.WriteLine($"TypeIdentifier: {entry.TypeIdentifier}, CatalogPath: {entry.CatalogPath}"); 62 | } 63 | } 64 | 65 | [Test] 66 | public void CreateMasterCopy() 67 | { 68 | var masterCopiesFolder = Project.ProjectLibrary.MasterCopyFolder; 69 | 70 | var device = Project.Devices.First(x => 71 | x.DeviceItems.SingleOrDefault(n => n.Classification == DeviceItemClassifications.HM).Name.Contains("S120")); 72 | 73 | var masterCopy = masterCopiesFolder.MasterCopies.Create(device); 74 | device.Delete(); 75 | 76 | var newDevice = Project.Devices.CreateFrom(masterCopy); 77 | Console.WriteLine($"Device could be created: {newDevice != null}"); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/TagTableSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using System.Xml.Linq; 5 | using NUnit.Framework; 6 | using Siemens.Engineering; 7 | using Siemens.Engineering.HW.Features; 8 | using Siemens.Engineering.SW; 9 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 10 | 11 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7.PLC; 12 | 13 | [TestFixture("Step7.zap20")] 14 | public class TagTableSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 15 | { 16 | [TearDown] 17 | public void CleanupTempFile() 18 | { 19 | if (!string.IsNullOrEmpty(_lastTempPath) && File.Exists(_lastTempPath)) 20 | { 21 | File.Delete(_lastTempPath); 22 | _lastTempPath = null; 23 | } 24 | } 25 | 26 | private string _lastTempPath; 27 | 28 | [Test] 29 | public void EditExistingTags() 30 | { 31 | var plcDevice = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 32 | var plcSoftware = plcDevice.DeviceItems[1].GetService().Software as PlcSoftware; 33 | var myTagTable = plcSoftware?.TagTableGroup.TagTables.FirstOrDefault(x => x.Name == "DemocaseAppTagTable"); 34 | var myTag = myTagTable?.Tags.FirstOrDefault(); 35 | 36 | if (myTag != null) 37 | { 38 | myTag.Name = "NewTagName2"; 39 | } 40 | } 41 | 42 | [Test] 43 | public void EditExistingTagsViaExportImport() 44 | { 45 | var plcDevice = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 46 | var plcSoftware = plcDevice.DeviceItems[1].GetService().Software as PlcSoftware; 47 | var myTagTable = plcSoftware?.TagTableGroup.TagTables.FirstOrDefault(x => x.Name == "DemocaseAppTagTable"); 48 | 49 | // Use a generic temp path for export 50 | var tempPath = Path.Combine(Path.GetTempPath(), "DemocaseAppTagTable_export.xml"); 51 | _lastTempPath = tempPath; 52 | myTagTable?.Export(new FileInfo(tempPath), ExportOptions.WithDefaults); 53 | 54 | // Read the exported XML file content 55 | var xmlContent = File.ReadAllText(tempPath); 56 | 57 | var xdoc = XDocument.Parse(xmlContent); 58 | 59 | // Get all SW.Tags.PlcTag elements 60 | var plcTags = xdoc.Descendants("SW.Tags.PlcTag").ToList(); 61 | 62 | var firstTag = plcTags.FirstOrDefault(); 63 | if (firstTag != null) 64 | { 65 | var nameElement = firstTag.Element("AttributeList")?.Element("Name"); 66 | if (nameElement != null) 67 | { 68 | nameElement.Value = "NewTagName"; 69 | } 70 | } 71 | 72 | // Save the modified XML back to the file 73 | xdoc.Save(tempPath); 74 | 75 | // Import the modified XML back into the tag table 76 | plcSoftware?.TagTableGroup.TagTables?.Import(new FileInfo(tempPath), ImportOptions.Override); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/NetworkSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.HW.Features; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7; 10 | 11 | [TestFixture("Step7.zap20")] 12 | public class NetworkSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void PLC_Et200Connection() 16 | { 17 | var project = Project; 18 | 19 | var plc = project.Devices.CreateWithItem("OrderNumber:6ES7 515-2UM01-0AB0/V2.9", "", ""); 20 | var et200 = 21 | project.UngroupedDevicesGroup.Devices.CreateWithItem("OrderNumber:6ES7 155-6AU00-0CN0/V3.0", "", ""); 22 | 23 | //Get NetworkInterface for plc and et200 (here the first profinet interface) 24 | var networkInterfacePlc = plc.DeviceItems 25 | .First(x => x.Classification == DeviceItemClassifications.CPU) 26 | .DeviceItems 27 | .First(x => x.Name.Contains("PROFINET")).GetService(); 28 | 29 | var networkInterfaceEt200 = et200.DeviceItems 30 | .First(x => x.Classification == DeviceItemClassifications.HM) 31 | .DeviceItems.First(x => x.Name.Contains("PROFINET")).GetService(); 32 | 33 | //Get the nodes for connection of the subnet 34 | var et200Node = networkInterfaceEt200.Nodes.First(); 35 | var plcNode = networkInterfacePlc.Nodes.First(); 36 | 37 | //Code if profinet interface from plc is already connected to subnet 38 | var plcSubnet = plcNode.ConnectedSubnet; 39 | 40 | //If not connected, create subnet 41 | plcSubnet ??= plcNode.CreateAndConnectToSubnet("TestSubnet"); 42 | 43 | //ConnectToASubnet 44 | et200Node.ConnectToSubnet(plcSubnet); 45 | 46 | 47 | //Get IoConnector for connection of the io system 48 | var ioConnectorEt200 = networkInterfaceEt200.IoConnectors.First(); 49 | 50 | //Code if profinet interface from plc is already connected to ioSystem 51 | //If not connected, create ioSystem 52 | var plcIoSystem = networkInterfacePlc.IoControllers.First().IoSystem ?? 53 | networkInterfacePlc.IoControllers.First().CreateIoSystem("TestIOSystem"); 54 | 55 | //Connect ioSystem from et200 56 | ioConnectorEt200.ConnectToIoSystem(plcIoSystem); 57 | } 58 | 59 | [Test] 60 | public void GetProfinetInterface_PLC() 61 | { 62 | var device = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 63 | 64 | var cpu = device.DeviceItems.First(x => x.Classification == DeviceItemClassifications.CPU); 65 | var profinetInterfaces = cpu.DeviceItems 66 | .Where(d => d.GetAttributeInfos().Select(x => x.Name).Contains("PnSendClock")).ToList(); 67 | 68 | Console.WriteLine($"Found {profinetInterfaces.Count} Profinet Interfaces"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/TiaProcessSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering; 6 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 7 | 8 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7; 9 | 10 | [TestFixture("Step7.zap20")] 11 | public class TiaProcessSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 12 | { 13 | [Test] 14 | public void StartTiaTest() 15 | { 16 | // Start a new TIA Portal 17 | var tia = new Siemens.Engineering.TiaPortal(TiaPortalMode.WithUserInterface); 18 | // Wait 2 seconds 19 | Thread.Sleep(2000); 20 | // Close TIA Portal 21 | tia.GetCurrentProcess().Dispose(); 22 | } 23 | 24 | [Test] 25 | public void StartTiaAndOpenProjectTest() 26 | { 27 | Siemens.Engineering.TiaPortal tia = new(TiaPortalMode.WithUserInterface); 28 | FileInfo fileInfo = new("C:/MyPathToTheTiaProject.ap19"); //TODO modify the path as needed 29 | 30 | tia.Projects.Open(fileInfo); 31 | 32 | tia.GetCurrentProcess().Dispose(); 33 | } 34 | 35 | [Test] 36 | public void StartTiaAndRetrieveProjectTest() 37 | { 38 | // Start a new TIA Portal 39 | Siemens.Engineering.TiaPortal tia = new(TiaPortalMode.WithUserInterface); 40 | var myStep7ProjectArchivePath = 41 | Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "resources", "Step7.zap20"); 42 | FileInfo sourcePath = new(myStep7ProjectArchivePath); 43 | DirectoryInfo targetPath = new(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); 44 | 45 | var tiaProject = tia.Projects.Retrieve(sourcePath, targetPath); 46 | Console.WriteLine($"Tia Project retrieved {tiaProject != null}"); 47 | tiaProject?.Close(); 48 | tia.GetCurrentProcess().Dispose(); 49 | targetPath.Delete(true); 50 | } 51 | 52 | [Test] 53 | public void ArchiveProjectTest() 54 | { 55 | var project = Project; 56 | project.Save(); 57 | project.Archive(new DirectoryInfo(Path.GetTempPath()), "dummy.zap20", 58 | ProjectArchivationMode.Compressed); 59 | 60 | var fileInfo = new FileInfo(Path.Combine(Path.GetTempPath(), "dummy.zap20")); 61 | if (fileInfo.Exists) 62 | { 63 | fileInfo.Delete(); 64 | } 65 | } 66 | 67 | [Test] 68 | public void ExclusiveAccess() 69 | { 70 | using var exclusiveAccess = TiaPortalInstance.ExclusiveAccess("Test"); 71 | exclusiveAccess.Text = "Start of the program"; 72 | 73 | //... 74 | 75 | exclusiveAccess.Text = "End of the program"; 76 | } 77 | 78 | [Test] 79 | public void Transaction() 80 | { 81 | using var exclusiveAccess = TiaPortalInstance.ExclusiveAccess("Test"); 82 | 83 | using var transaction = exclusiveAccess.Transaction(Project, "Test"); 84 | var i = 1; 85 | 86 | do 87 | { 88 | i++; 89 | } while (i < 10000); 90 | 91 | exclusiveAccess.Text = "Test 123"; 92 | 93 | transaction.CommitOnDispose(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/SecuritySnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using System.Security; 5 | using NUnit.Framework; 6 | using Siemens.Engineering.HW; 7 | using Siemens.Engineering.HW.Features; 8 | using Siemens.Engineering.Umac; 9 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 10 | 11 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7; 12 | 13 | [TestFixture("Step7.zap20")] 14 | public class SecuritySnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 15 | { 16 | [Test] 17 | public void CreateProjectRoles() 18 | { 19 | var umacConfigurator = Project.GetService(); 20 | 21 | // create a custom role for the webServer 22 | var adminRole = umacConfigurator.CustomRoles.Create("Admin", "Admin Role for MCS Web Server Application"); 23 | 24 | //get UMAC device from plc device 25 | var umacDevice = Project.Devices.CreateWithItem("OrderNumber:6ES7 518-4UP00-0AB0/V3.1", "", "") 26 | .GetService(); 27 | if (umacDevice != null) 28 | { 29 | var deviceFunctionRightsAssociation = umacDevice.AvailableDeviceFunctionRights; 30 | 31 | Console.WriteLine(string.Join("\n", 32 | deviceFunctionRightsAssociation.Select(r => $"Name: {r.Name}, Identifier: {r.Identifier}"))); 33 | 34 | //Select and assign the needed deviceFunctionRight 35 | adminRole.AssignDeviceFunctionRight(umacDevice, deviceFunctionRightsAssociation.First()); 36 | } 37 | 38 | umacConfigurator.ProjectUsers.Create("Admin", GetSecureString("AdminAdmin123")); 39 | } 40 | 41 | [Test] 42 | public void SetPasswordProtectionTest() 43 | { 44 | // Password should contain minimum 8 characters and maximum 120 characters. Also, 1 uppercase, 1 lowercase, 1 number and 1 special character. 45 | var secureString = GetSecureString("Test12345!"); 46 | 47 | var plc = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 48 | var cpu = plc.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.CPU); 49 | 50 | var masterSecretConfigurator = cpu.GetService(); 51 | masterSecretConfigurator.Protect(secureString); 52 | } 53 | 54 | [Test] 55 | public void IsProjectProtected() 56 | { 57 | var umacConfigurator = Project.GetService(); 58 | var engineeringFunctionRights = umacConfigurator.EngineeringFunctionRights; 59 | if (engineeringFunctionRights.Any()) 60 | { 61 | Console.WriteLine("Project is protected"); 62 | } 63 | else 64 | { 65 | Console.WriteLine("Project is unprotected"); 66 | } 67 | } 68 | 69 | private static SecureString GetSecureString(string value) 70 | { 71 | var secureStr = new SecureString(); 72 | if (string.IsNullOrEmpty(value)) 73 | { 74 | return secureStr; 75 | } 76 | 77 | foreach (var t in value) 78 | { 79 | secureStr.AppendChar(t); 80 | } 81 | 82 | secureStr.MakeReadOnly(); 83 | return secureStr; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TIA Portal Openness Code Snippets 2 | 3 | ## Table of Contents 4 | 5 | 1. [Goal](#goal) 6 | 2. [Features](#features) 7 | 3. [Getting Started](#getting-started) 8 | 4. [Requirements](#requirements) 9 | 5. [Contributing](#contributing) 10 | 6. [License](#license) 11 | 12 | ## Goal 13 | 14 | This repository provides small, easy-to-understand code snippets demonstrating how to work with the latest TIA Portal Openness API (currently V20). 15 | 16 | Use this repository to learn and experiment with the TIA Portal Openness API in a modular way. 17 | 18 | > **Note:** 19 | > The test methods in this repository are intended for demonstration and experimentation only. 20 | > They are **not** real test cases and do **not** use any assertions. 21 | > The TestFramework is used solely to enable the execution of each method individually. 22 | 23 | ## Features 24 | 25 | - Modular code snippets for TIA Portal Openness API (V20). 26 | - Automatically starts a TIA Portal instance if not already running. 27 | - Test methods for easy execution and experimentation. 28 | - Support for different TIA Portal setups: 29 | - Step7 30 | - Step7 + Startdrive 31 | - Step7 + Startdrive + Dcc 32 | 33 | ## Getting Started 34 | 35 | Follow these steps to set up and use the repository: 36 | 37 | 1. **Clone the Repository** 38 | 39 | ```bash 40 | git clone https://github.com/siemens/tia-portal-openness-code-snippets.git 41 | cd tia-portal-openness-code-snippets 42 | ``` 43 | 44 | 2. **Install Dependencies** 45 | 46 | Ensure you have the required version of TIA Portal installed (see the "Requirements" section below). 47 | 48 | 3. **Open the Solution** 49 | 50 | Based on your TIA Portal setup, open the appropriate solution file (.slnf or .sln) as described in the "Requirements" section. 51 | 52 | 4. **Run Tests** 53 | 54 | Open the Test Explorer: 55 | 56 | ![TestExplorerMenuEntry.png](docs/images/TestExplorerMenuEntry.png) 57 | 58 | Execute the test methods to explore the code snippets. Each snippet is designed to run independently. Select one and click the Run button: 59 | 60 | ![TestExplorerMethodSelection.png](docs/images/TestExplorerMethodSelection.png) 61 | 62 | ## Requirements 63 | 64 | To build the project, select the appropriate solution filter file (`.slnf`) or the full solution file (`.sln`) based on your TIA Portal installation setup: 65 | 66 | ### 1. Installed Step7 67 | 68 | Use the following solution filter file: [Step7ProjectSubset.slnf](src/Step7ProjectSubset.slnf) 69 | 70 | ![Step7 Project Subset](docs/images/Step7ProjectSubset.png) 71 | 72 | --- 73 | 74 | ### 2. Installed Step7 + Startdrive 75 | 76 | Use the following solution filter file: [StartdriveProjectSubset.slnf](src/StartdriveProjectSubset.slnf) 77 | 78 | ![Startdrive Project Subset](docs/images/StartdriveProjectSubset.png) 79 | 80 | --- 81 | 82 | ### 3. Installed Step7 + Startdrive + Dcc 83 | 84 | Use the full solution file: [TiaPortal.Openness.CodeSnippets.sln](src/TiaPortal.Openness.CodeSnippets.sln) 85 | 86 | ![Full Solution](docs/images/TiaPortal.Openness.CodeSnippets.png) 87 | 88 | ## Contributing 89 | 90 | We welcome contributions to improve this repository! Here's how you can contribute: Check [CONTRIBUTING.md](/CONTRIBUTING.md) 91 | 92 | ## License 93 | 94 | © Siemens 2025 95 | 96 | Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See [LICENSE.md](/LICENSE.md). 97 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct - UseCaseBasedDoku Modular Application Creator Module Builder 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behaviour that contributes to a positive environment for our 15 | community include: 16 | 17 | * Demonstrating empathy and kindness toward other people 18 | * Being respectful of differing opinions, viewpoints, and experiences 19 | * Giving and gracefully accepting constructive feedback 20 | * Accepting responsibility and apologising to those affected by our mistakes, 21 | and learning from the experience 22 | * Focusing on what is best not just for us as individuals, but for the 23 | overall community 24 | 25 | Examples of unacceptable behaviour include: 26 | 27 | * The use of sexualised language or imagery, and sexual attention or advances 28 | * Trolling, insulting or derogatory comments, and personal or political attacks 29 | * Public or private harassment 30 | * Publishing others' private information, such as a physical or email 31 | address, without their explicit permission 32 | * Other conduct which could reasonably be considered inappropriate in a 33 | professional setting 34 | 35 | ## Our Responsibilities 36 | 37 | Project maintainers are responsible for clarifying and enforcing our standards of 38 | acceptable behaviour and will take appropriate and fair corrective action in 39 | response to any instances of unacceptable behaviour. 40 | 41 | Project maintainers have the right and responsibility to remove, edit, or reject 42 | comments, commits, code, wiki edits, issues, and other contributions that are 43 | not aligned to this Code of Conduct, or to ban 44 | temporarily or permanently any contributor for other behaviours that they deem 45 | inappropriate, threatening, offensive, or harmful. 46 | 47 | ## Scope 48 | 49 | This Code of Conduct applies within all community spaces, and also applies when 50 | an individual is officially representing the community in public spaces. 51 | Examples of representing our community include using an official e-mail address, 52 | posting via an official social media account, or acting as an appointed 53 | representative at an online or offline event. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behaviour may be 58 | reported to the community leaders responsible for enforcement at . 59 | All complaints will be reviewed and investigated promptly and fairly. 60 | 61 | All community leaders are obligated to respect the privacy and security of the 62 | reporter of any incident. 63 | 64 | ## Attribution 65 | 66 | This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org/), version 67 | [1.4](https://www.contributor-covenant.org/version/1/4/code-of-conduct/code_of_conduct.md) and 68 | [2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct/code_of_conduct.md), 69 | and was generated by [contributing-gen](https://github.com/bttger/contributing-gen). -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive/AttributePathSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Collaboration.Net.TiaPortal.Openness.Extensions.AttributeHandling; 6 | using Siemens.Engineering.HW; 7 | using Siemens.Engineering.HW.Features; 8 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 9 | 10 | namespace TiaPortal.Openness.CodeSnippets.WithExtensions.StartDrive; 11 | 12 | [TestFixture("Startdrive.zap20")] 13 | public class AttributePathSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 14 | { 15 | [Test] 16 | public void ReadOutAllDevicePaths() 17 | { 18 | var devices = TiaPortalInstance.ProjectBase().AllDevices(); 19 | foreach (var device in devices) 20 | { 21 | Console.WriteLine(device.GetPath()); 22 | } 23 | } 24 | 25 | [Test] 26 | public void ReadOutAllMotorModulePaths() 27 | { 28 | var motorModules = TiaPortalInstance.ProjectBase() 29 | .AllStartdriveDevices() 30 | .Where(d => d.IsSinamicsS120()) 31 | .SelectMany(s => s.DeviceItems) 32 | .SelectMany(i => i.MotorPowerModules()) 33 | .ToList(); 34 | 35 | Console.WriteLine($"Motor Modules Found: {motorModules.Count()}"); 36 | Console.WriteLine($"{"DeviceItem Name",-25}\tPath to Motor Module"); 37 | 38 | foreach (var motorModule in motorModules) 39 | { 40 | Console.WriteLine($"{motorModule.Parent().Name,-25}\t{motorModule.GetPath()}"); 41 | } 42 | } 43 | 44 | [Test] 45 | public void PathConcept_FirstIntroduction() 46 | { 47 | var tia = TiaPortalInstance; 48 | var project = Project; 49 | 50 | var engineeringObject = project.Devices.First(x => x.Name == "S120Democase").HeadModule().DeviceItems[0] 51 | .GetService().Nodes.First(); 52 | 53 | //Save in string 54 | var path = engineeringObject.GetPath(); 55 | 56 | //return in engineeringObject 57 | var engineeringObjectNew = path.ToEngineeringObject(tia); 58 | 59 | Console.WriteLine($"Objects are equal: {Equals(engineeringObject, engineeringObjectNew)}"); 60 | } 61 | 62 | [Test] 63 | public void PathConcept_GetEngineeringObjectWithIdentifier() 64 | { 65 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 66 | 67 | var allDeviceItems = device.AllDeviceItems().ToCachedEnumerable(); 68 | 69 | var allMotors = allDeviceItems.GetEngineeringObjectsWithIdentifier(ObjectIdentifier.Motor).ToList(); 70 | var allEncoder = allDeviceItems.GetEngineeringObjectsWithIdentifier(ObjectIdentifier.Encoder).ToList(); 71 | 72 | allMotors.ForEach(x => 73 | Console.WriteLine($"Objects are equal: {Equals(ObjectIdentifier.Motor, x.GetObjectIdentifierEnum())}")); 74 | allEncoder.ForEach(x => 75 | Console.WriteLine($"Objects are equal: {Equals(ObjectIdentifier.Encoder, x.GetObjectIdentifierEnum())}")); 76 | } 77 | 78 | [Test] 79 | public void CompositionPath() 80 | { 81 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 82 | var nodeComposition = device.HeadModule().ProfinetInterfaces().First().AsNetworkInterface().Nodes; 83 | var nodeCompositionPath = nodeComposition.GetPath(); 84 | Console.WriteLine(nodeCompositionPath); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/ProgramBlocks/Resources/PLCBlocks/Block_1: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 | 14 | Optimized 15 | 100 16 | Block_1 17 | 18 | 1 19 | SCL 20 | false 21 | 22 | 23 | 24 | 25 | 26 | 27 | en-US 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | TRUE 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Statement section IF 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | SCL 59 | 60 | 61 | 62 | 63 | 64 | 65 | en-US 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | en-US 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | en-US 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/ProgramBlocks/Resources/PLCBlocks/Block_2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 | 14 | Optimized 15 | 100 16 | Block_2 17 | 18 | 1 19 | SCL 20 | false 21 | 22 | 23 | 24 | 25 | 26 | 27 | en-US 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | TRUE 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Statement section IF 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | SCL 59 | 60 | 61 | 62 | 63 | 64 | 65 | en-US 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | en-US 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | en-US 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/ProgramBlocks/Resources/PLCBlocks/Block_3: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 | 14 | Optimized 15 | 100 16 | Block_3 17 | 18 | 1 19 | SCL 20 | false 21 | 22 | 23 | 24 | 25 | 26 | 27 | en-US 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | TRUE 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Statement section IF 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | SCL 59 | 60 | 61 | 62 | 63 | 64 | 65 | en-US 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | en-US 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | en-US 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/ProgramBlocks/Resources/PLCBlocks/Block_4: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 | 14 | Optimized 15 | 100 16 | Block_4 17 | 18 | 1 19 | SCL 20 | false 21 | 22 | 23 | 24 | 25 | 26 | 27 | en-US 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | TRUE 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Statement section IF 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | SCL 59 | 60 | 61 | 62 | 63 | 64 | 65 | en-US 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | en-US 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | en-US 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/ProgramBlocks/Resources/PLCBlocks/Block_5: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 | 14 | Optimized 15 | 100 16 | Block_5 17 | 18 | 1 19 | SCL 20 | false 21 | 22 | 23 | 24 | 25 | 26 | 27 | en-US 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | TRUE 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Statement section IF 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | SCL 59 | 60 | 61 | 62 | 63 | 64 | 65 | en-US 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | en-US 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | en-US 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/SafetySnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.MC.Drives; 6 | using Siemens.Engineering.MC.Drives.DFI; 7 | using Siemens.Engineering.MC.Drives.Enums; 8 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 9 | 10 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 11 | 12 | [TestFixture("Startdrive.zap20")] 13 | public class SafetySnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 14 | { 15 | [Test] 16 | public void SafetyIntegratedCalculateChecksumForNextGeneration() 17 | { 18 | var device = Project.Devices.First(x => x.Name == "SINAMICS S210V61"); 19 | var driveControl = device.DeviceItems.First(); 20 | 21 | var driveObject = driveControl.GetService().DriveObjects.First(); 22 | var driveFunctionInterface = driveObject.GetService(); 23 | var succeeded = driveFunctionInterface.SafetyCommissioning.UpdateCheckSums(); 24 | 25 | Console.WriteLine($"CalculateCheckSum succeeded: {succeeded}"); 26 | } 27 | 28 | [Test] 29 | public void SafetyIntegratedExampleNewGeneration_ActivateSTO() 30 | { 31 | var device = Project.Devices.First(x => x.Name == "SINAMICS S210V61"); 32 | var driveControl = device.DeviceItems.First(); 33 | 34 | var driveObject = driveControl.GetService().DriveObjects.First(); 35 | var parameters = driveObject.Parameters; 36 | 37 | //Enable Safety via ProfiSafe 38 | parameters.Find("p9603").Bits.Single(x => x.Name == "p9603.1").Value = 1; 39 | 40 | //Enable STO 41 | parameters.Find("p9604").Bits.Single(x => x.Name == "p9604.0").Value = 1; 42 | 43 | var driveFunctionInterface = driveObject.GetService(); 44 | var succeeded = driveFunctionInterface.SafetyCommissioning.UpdateCheckSums(); 45 | 46 | Console.WriteLine($"CalculateCheckSum succeeded: {succeeded}"); 47 | } 48 | 49 | 50 | [Test] 51 | public void SafetyIntegratedExampleNewGeneration_ChangeAxisType() 52 | { 53 | var device = Project.Devices.First(x => x.Name == "SINAMICS S210V61"); 54 | var driveControl = device.DeviceItems.First(); 55 | 56 | var driveObject = driveControl.GetService().DriveObjects.First(); 57 | var parameters = driveObject.Parameters; 58 | 59 | //Enable Safety via ProfiSafe 60 | parameters.Find("p9603").Bits.Single(x => x.Name == "p9603.1").Value = 1; 61 | 62 | //Set Axis Type 63 | var dfi = driveObject.GetService(); 64 | dfi.FunctionInUse.SetSIAxisType(RotaryLinearFlag.Linear); 65 | 66 | var driveFunctionInterface = driveObject.GetService(); 67 | var succeeded = driveFunctionInterface.SafetyCommissioning.UpdateCheckSums(); 68 | 69 | Console.WriteLine($"CalculateCheckSum succeeded: {succeeded}"); 70 | } 71 | 72 | 73 | [Test] 74 | public void SafetyIntegratedExampleS120_ActivateSTO() 75 | { 76 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 77 | var axis = device.DeviceItems.First(x => x.Name == "RedAxis"); 78 | 79 | var driveObject = axis.GetService().DriveObjects.First(); 80 | var parameters = driveObject.Parameters; 81 | 82 | //Enable BasicSafety via ProfiSafe 83 | parameters.Find("p9601").Bits.Single(x => x.Name == "p9601.3").Value = 1; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/TechnologyObjectSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using NUnit.Framework; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.HW.Features; 7 | using Siemens.Engineering.MC.Drives; 8 | using Siemens.Engineering.SW; 9 | using Siemens.Engineering.SW.TechnologicalObjects; 10 | using Siemens.Engineering.SW.TechnologicalObjects.Motion; 11 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 12 | 13 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 14 | 15 | [TestFixture("Startdrive.zap20")] 16 | public class TechnologyObjectSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 17 | { 18 | [Test] 19 | public void GetConnectedDriveObjectFromTo() 20 | { 21 | var plc = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 22 | var to = (plc.DeviceItems[1].GetService().Software as PlcSoftware)?.TechnologicalObjectGroup 23 | .TechnologicalObjects.First(x => x.Name == "PositioningAxis_blue"); 24 | if (to == null) 25 | { 26 | Console.WriteLine("To not found"); 27 | return; 28 | } 29 | 30 | var connectedDriveObject = GetConnectedDriveAxisFromToSmootherWay(to); 31 | Console.WriteLine(connectedDriveObject.Parent.GetAttribute("Name")); 32 | } 33 | 34 | public DriveObject? GetConnectedDriveAxisFromToSmootherWay(TechnologicalInstanceDB to) 35 | { 36 | var plc = to.Parent as Device; 37 | var inputAddress = (int)to.GetService().ActorInterface 38 | .GetAttribute("InputAddress") / 8; 39 | 40 | var cpu = plc.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.CPU); 41 | var connectedIoSystems = GetAllConnectedIoSystems(cpu); 42 | var connectedIoDevices = connectedIoSystems.SelectMany(ioSystem => ioSystem.ConnectedIoDevices); 43 | 44 | var connectedSinamicsDevices = connectedIoDevices 45 | .Select(ioConnector => ioConnector.Parent as Device) 46 | .Where(IsSinamics) 47 | .ToList(); 48 | 49 | DriveObject? connectedDriveObject = null; 50 | 51 | foreach (var drive in connectedSinamicsDevices) 52 | { 53 | connectedDriveObject = GetConnectedDriveObject(drive, inputAddress); 54 | if (connectedDriveObject != null) 55 | { 56 | break; 57 | } 58 | } 59 | 60 | return connectedDriveObject; 61 | } 62 | 63 | private static IEnumerable GetAllConnectedIoSystems(DeviceItem deviceItem) 64 | { 65 | var allNetworkInterfaces = 66 | deviceItem.DeviceItems.Select(x => x.GetService()).Where(x => x != null); 67 | var ioSystems = allNetworkInterfaces.SelectMany(x => x.IoControllers).Select(x => x.IoSystem) 68 | .Where(x => x != null); 69 | return ioSystems; 70 | } 71 | 72 | public DriveObject? GetConnectedDriveObject(Device drive, int inputAddress) 73 | { 74 | var allDriveObjects = drive.DeviceItems.Select(x => x.GetService()).Where(x => x != null) 75 | .Select(x => x.DriveObjects.First()); 76 | 77 | return (from driveObject in allDriveObjects 78 | let telegrams = driveObject.Telegrams 79 | where telegrams.Any(telegram => (int)telegram.Addresses[0].GetAttribute("StartAddress") == inputAddress) 80 | select driveObject).FirstOrDefault(); 81 | } 82 | 83 | public bool IsSinamics(Device device) 84 | { 85 | return device.DeviceItems.Any((Func)(di => 86 | di.GetService() != null)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/TransferAreaSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | 5 | using NUnit.Framework; 6 | using Siemens.Engineering.HW; 7 | using Siemens.Engineering.HW.Features; 8 | using Siemens.Engineering.SW; 9 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 10 | 11 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7 12 | { 13 | [TestFixture("Step7.zap20")] 14 | public class TransferAreaSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 15 | { 16 | [Test] 17 | public void createNewTransferAreaWithSameIOAddressesFromExistingTransferArea() 18 | { 19 | // Find master and slave PLCs 20 | var leadingPlc = Project.Devices.First(x => x.Name == "PLC_S120Democase").DeviceItems.First(x => x.Name == "PLC_S120Democase"); 21 | var followingPlc2 = Project.Devices.First(x => x.Name == "PLC_2").DeviceItems.First(x => x.Name == "PLC_2"); 22 | 23 | // Get Network interfaces for master and slaves 24 | var nwItf_leadingPlc = leadingPlc.DeviceItems.First(x => x.GetService() is NetworkInterface nwItf && nwItf != null && nwItf.InterfaceType == NetType.Ethernet).GetService(); 25 | var nwItf_followingPlc2 = followingPlc2.DeviceItems.First(x => x.GetService() is NetworkInterface nwItf && nwItf != null && nwItf.InterfaceType == NetType.Ethernet).GetService(); 26 | 27 | // get existing transfer area to PLC1 28 | var existingTransferArea = nwItf_leadingPlc.MulticastableTransferAreas.FirstOrDefault(x => x.Name == "LeadToPlc1"); 29 | 30 | 31 | // Create new Multicast Transfer area with same IO addresses on LeadPlc from existing transfer 32 | var newTransferAreaFromLeadToPlc2 = nwItf_followingPlc2.MulticastableTransferAreas.Create(existingTransferArea, existingTransferArea.Type); 33 | 34 | // Set Processimages 35 | var mcServoObNumber = 91; 36 | 37 | // Set ProcessImage for following PLC 2 38 | var address_plc2 = newTransferAreaFromLeadToPlc2.Addresses.First(); 39 | var mcServoBlock_plc2 = (followingPlc2.GetService().Software as PlcSoftware).BlockGroup.Blocks.FirstOrDefault(x => x.Number == mcServoObNumber); 40 | if (mcServoBlock_plc2 != null) 41 | { 42 | var processImagePartNumber_plc2 = mcServoBlock_plc2.GetAttribute("ProcessImagePartNumber"); 43 | address_plc2.SetAttribute("ProcessImage", Convert.ToInt32(processImagePartNumber_plc2)); 44 | } 45 | 46 | // Set ProcessImage for Leading PLC 47 | var address_LeadPlc = newTransferAreaFromLeadToPlc2.PartnerTransferAreas.First().Addresses.First(); 48 | var mcServoBlock_LeadPlc = (leadingPlc.GetService().Software as PlcSoftware).BlockGroup.Blocks.FirstOrDefault(x => x.Number == mcServoObNumber); 49 | if (mcServoBlock_LeadPlc != null) 50 | { 51 | var processImagePartNumber_LeadPlc = mcServoBlock_LeadPlc.GetAttribute("ProcessImagePartNumber"); 52 | address_LeadPlc.SetAttribute("ProcessImage", Convert.ToInt32(processImagePartNumber_LeadPlc)); 53 | 54 | } 55 | 56 | // Known Bug: 57 | // address_plc2.Parent; => Accessing the Parent of address leads to crash of TIA Portal; That is also the reason why OpnsExplorer crashes if you try to access the address 58 | 59 | //address_plc2.StartAddress = 1000; // set input-adress for plc2 if required 60 | 61 | var newTransferAreaFromPlc2ToLead = nwItf_followingPlc2.MulticastableTransferAreas.Create(nwItf_leadingPlc, TransferAreaType.DDX, "Plc2ToLead", 1); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/OnlineSnippets.cs: -------------------------------------------------------------------------------- 1 | using System.Security; 2 | using NUnit.Framework; 3 | using Siemens.Engineering.Download; 4 | using Siemens.Engineering.Download.Configurations; 5 | using Siemens.Engineering.HW; 6 | using Siemens.Engineering.Online; 7 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 8 | 9 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7; 10 | 11 | [TestFixture("Step7.zap20")] 12 | public class OnlineSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 13 | { 14 | [Test] 15 | public void GoOnline() 16 | { 17 | var device = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 18 | var onlineProvider = device.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.CPU) 19 | .GetService(); 20 | var configuration = onlineProvider.Configuration; 21 | var configurationMode = configuration.Modes.Find("PN/IE"); 22 | const string InterfaceName = "Intel(R) Ethernet Connection I217 - LM"; 23 | try 24 | { 25 | var pcInterface = configurationMode.PcInterfaces.Find(InterfaceName, 1); 26 | if (pcInterface == null) 27 | { 28 | throw new Exception($"Could not find interface by name: {InterfaceName}"); 29 | } 30 | 31 | var targetConfiguration = pcInterface.TargetInterfaces[0]; 32 | configuration.ApplyConfiguration(targetConfiguration); 33 | var onlineState = onlineProvider.GoOnline(); 34 | Console.WriteLine(onlineState); 35 | } 36 | catch (Exception e) 37 | { 38 | Console.WriteLine(e); 39 | } 40 | } 41 | 42 | [Test] 43 | public void Download() 44 | { 45 | // Get the DownloadProvider 46 | var device = Project.Devices.First(x => x.Name == "PLC_S120Democase"); 47 | var downloadProvider = device.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.CPU) 48 | .GetService(); 49 | 50 | // Get the TargetConfiguration 51 | var configuration = downloadProvider.Configuration; 52 | var configurationMode = configuration.Modes.Find("PN/IE"); 53 | const string InterfaceName = "PLCSIM"; 54 | try 55 | { 56 | var pcInterface = configurationMode.PcInterfaces.Find(InterfaceName, 1); 57 | if (pcInterface == null) 58 | { 59 | throw new Exception($"Could not find interface by name: {InterfaceName}"); 60 | } 61 | 62 | var targetConfiguration = pcInterface.TargetInterfaces[0]; 63 | 64 | // Set the DownloadOptions 65 | const DownloadOptions DownloadOptions = DownloadOptions.SoftwareOnlyChanges; 66 | const string SafetyPassword = "HelloWorld!"; 67 | 68 | // Start Download 69 | downloadProvider.Download(targetConfiguration, preDownload => 70 | { 71 | if (preDownload is DownloadPasswordConfiguration downloadPasswordConfiguration) 72 | { 73 | downloadPasswordConfiguration.SetPassword(GetSecureString(SafetyPassword)); 74 | } 75 | }, _ => { }, DownloadOptions); 76 | } 77 | catch (Exception e) 78 | { 79 | Console.WriteLine(e); 80 | } 81 | } 82 | 83 | private static SecureString GetSecureString(string value) 84 | { 85 | var secureStr = new SecureString(); 86 | if (string.IsNullOrEmpty(value)) 87 | { 88 | return secureStr; 89 | } 90 | 91 | foreach (var t in value) 92 | { 93 | secureStr.AppendChar(t); 94 | } 95 | 96 | secureStr.MakeReadOnly(); 97 | return secureStr; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/TelegramSnippets.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Siemens.Engineering.HW; 3 | using Siemens.Engineering.MC.Drives; 4 | using Siemens.Engineering.MC.Drives.Enums; 5 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 6 | 7 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 8 | 9 | [TestFixture("Startdrive.zap20")] 10 | public class TelegramSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 11 | { 12 | [Test] 13 | public void SetPropertiesOfSafetyTelegram_SinamicsG() 14 | { 15 | var tia = TiaPortalInstance; 16 | 17 | var g115d = tia.Projects.First().Devices.Single(x => x.Name == "SINAMICS G120"); 18 | var hm = g115d.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.HM); 19 | 20 | var driveObjectContainer = hm.GetService(); 21 | 22 | var safetyTelegram = driveObjectContainer.DriveObjects.First().Telegrams 23 | .First(x => x.Type == TelegramType.SafetyTelegram); 24 | 25 | //Set FAddress 26 | safetyTelegram.SetAttribute("Failsafe_FDestinationAddress", 10); 27 | 28 | //Set FMonitoringTime 29 | safetyTelegram.SetAttribute("Failsafe_ManualAssignmentFMonitoringtime", true); 30 | safetyTelegram.SetAttribute("Failsafe_FMonitoringtime", 100); 31 | } 32 | 33 | [Test] 34 | public void SetPropertiesOfMainTelegram_SinamicsG() 35 | { 36 | var tia = TiaPortalInstance; 37 | 38 | var device = tia.Projects.First().Devices.Single(x => x.Name == "SINAMICS G120"); 39 | var deviceItem = device.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.HM); 40 | 41 | var driveObject = deviceItem.GetService().DriveObjects.First(); 42 | var mainTelegram = driveObject.Telegrams 43 | .First(x => x.Type == TelegramType.MainTelegram); 44 | mainTelegram.TelegramNumber = 20; 45 | } 46 | 47 | [Test] 48 | public void GetAddress() 49 | { 50 | var drive = Project.Devices.First(x => x.Name == "S120Democase"); 51 | var driveControl = drive.DeviceItems.FirstOrDefault(); 52 | 53 | var telegrams = driveControl?.GetService().DriveObjects.FirstOrDefault()?.Telegrams; 54 | 55 | var address = telegrams?.FirstOrDefault(x => x.Type == TelegramType.MainTelegram)?.Addresses.FirstOrDefault(); 56 | Console.WriteLine($"Address found: {address != null}"); 57 | } 58 | 59 | [Test] 60 | public void CreateAndAdjustSafetyTelegramAndAdjustMainTelegram_S120() 61 | { 62 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 63 | var driveAxis = device.DeviceItems.First(x => x.Name == "BlueAxis"); 64 | 65 | var driveObjectContainer = driveAxis.GetService(); 66 | var telegrams = driveObjectContainer.DriveObjects.First().Telegrams; 67 | 68 | if (telegrams.CanInsertSafetyTelegram(30)) 69 | { 70 | telegrams.InsertSafetyTelegram(30); 71 | } 72 | 73 | var safetyTelegram = telegrams.Single(x => x.Type == TelegramType.SafetyTelegram); 74 | 75 | //Set FAddress 76 | safetyTelegram.SetAttribute("Failsafe_FDestinationAddress", 10); 77 | 78 | var mainTelegram = telegrams.First(x => x.Type == TelegramType.MainTelegram); 79 | 80 | if (mainTelegram.CanChangeTelegram(999)) 81 | { 82 | mainTelegram.TelegramNumber = 999; 83 | } 84 | } 85 | 86 | [Test] 87 | public void SetTelegramLength() 88 | { 89 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 90 | var driveAxis = device.DeviceItems.Single(n => n.Name == "BlueAxis"); 91 | 92 | var driveObject = driveAxis.GetService().DriveObjects.First(); 93 | var telegrams = driveObject.Telegrams; 94 | 95 | var mainTelegram = telegrams.First(x => x.Type == TelegramType.MainTelegram); 96 | mainTelegram.ChangeSize(AddressIoType.Input, 10, false); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Startdrive/HardwareSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | using NUnit.Framework; 4 | using Siemens.Engineering.HW; 5 | using Siemens.Engineering.HW.Features; 6 | using Siemens.Engineering.MC.Drives; 7 | using Siemens.Engineering.MC.Drives.DFI; 8 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 9 | 10 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 11 | 12 | [TestFixture("Startdrive.zap20")] 13 | public class HardwareSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 14 | { 15 | [Test] 16 | public void SetDriveCliqConnections() 17 | { 18 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 19 | var driveAxis = device.DeviceItems.Single(n => n.Name == "BlueAxis"); 20 | 21 | var driveCliqInterface = driveAxis.DeviceItems.First().DeviceItems.First(); 22 | var axisPorts = driveCliqInterface.DeviceItems.Select(x => x.GetService()).ToList(); 23 | 24 | foreach (var port in axisPorts) 25 | { 26 | var connectedPort = port.ConnectedPorts.FirstOrDefault(); 27 | if (connectedPort != null) 28 | { 29 | port.DisconnectFromPort(connectedPort); 30 | } 31 | } 32 | 33 | var firstAxisPort = axisPorts.First(); 34 | var firstCuPort = device.DeviceItems[1].DeviceItems[2].DeviceItems.First(); 35 | 36 | var firstCuNetworkPort = firstCuPort.GetService(); 37 | firstAxisPort.ConnectToPort(firstCuNetworkPort); 38 | } 39 | 40 | [Test] 41 | public void PlugMotorModuleAndMotor_S120() 42 | { 43 | var device = Project.Devices.First(x => x.Name == "S120Democase"); 44 | var motorModule = device.PlugNew("OrderNumber:6SL3120-1TE15-0Axx//10002", "MotorModule", 65535); 45 | 46 | var driveAxis = motorModule.Parent as DeviceItem; 47 | 48 | var motor = driveAxis?.PlugNew("OrderNumber:1FK7011-xAK21-xTGx", "", 65535); 49 | 50 | Console.WriteLine($"Motor could be created: {motor != null}"); 51 | } 52 | 53 | [Test] 54 | public void CreateAndChangeMotor_S210() 55 | { 56 | // Create S210 Device 57 | var s210TypeIdentifier = "OrderNumber:6SL3210-5HB10-1xFx/V5.2.3/S210"; 58 | var device = Project.Devices.CreateWithItem(s210TypeIdentifier, "S210_New", "S210_NewDevice"); 59 | 60 | 61 | // Remove existing "dummy" synchronous motor 62 | var rack = device.DeviceItems.Single(x => x.TypeIdentifier.ToLower().Contains("system:rack")); 63 | var existingMotor = rack.DeviceItems.Single(x => x.TypeIdentifier.ToLower().Contains("xxxxx-xxxx")); 64 | existingMotor.Delete(); 65 | 66 | // Plug new Motor 67 | var motorTypeIdentifier = "OrderNumber:1FK2102-0AG1x-xSxx"; 68 | var newMotor = rack.PlugNew(motorTypeIdentifier, "NewMotor", 65535); 69 | } 70 | 71 | [Test] 72 | public void G115DModuleCreationWallMount() 73 | { 74 | const string TypeIdentifier = "OrderNumber:6SL3500-0XE50-7FA_/-"; 75 | 76 | var g115d = Project.Devices.CreateWithItem("OrderNumber:6SL3500-xxxxx-xFxx/4.7.14", "", ""); 77 | var deviceItem = g115d.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.HM) 78 | .PlugNew(TypeIdentifier, "", 3); 79 | 80 | Console.WriteLine($"DeviceItem could be created: {deviceItem != null}"); 81 | } 82 | 83 | 84 | [Test] 85 | public void G115DModuleCreation_MotorMountWith_2KJ8() 86 | { 87 | const string TypeIdentifier = "OrderNumber:6SL3500-0XE50-7FA_/-"; 88 | 89 | var g115d = Project.Devices.CreateWithItem("OrderNumber:6SL3500-xxxxx-xFxx/4.7.14", "", ""); 90 | 91 | var driveObject = g115d.DeviceItems.Single(x => x.Classification == DeviceItemClassifications.HM) 92 | .GetService().DriveObjects.First(); 93 | var dfi = driveObject.GetService(); 94 | 95 | dfi.Commissioning.SetSimoGearMlfb("2KJ8001-2EA10-3FG1-D0X"); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive/NetworkSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using System.Globalization; 5 | using NUnit.Framework; 6 | using Siemens.Engineering.HW; 7 | using Siemens.Engineering.HW.Features; 8 | using TiaPortal.Openness.CodeSnippets.WithExtensions.Setup; 9 | 10 | namespace TiaPortal.Openness.CodeSnippets.Plain.Startdrive; 11 | 12 | [TestFixture("Startdrive.zap20")] 13 | public class NetworkSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 14 | { 15 | [Test] 16 | public void IpAddressAndOnlineConfig() 17 | { 18 | var device = Project.AllStartdriveDevices().First(x => x.Name.Equals("S120Democase")); 19 | 20 | // Get TIA Portal Language and use for German "PROFINET-Schnittstelle" and English "PROFINET interface" 21 | var localization = TiaPortalInstance.SettingsFolders.Find("General").Settings.Find("UserInterfaceLanguage").Value.ToString(); 22 | var culture = new CultureInfo(localization); 23 | 24 | // Determine the appropriate PROFINET interface name based on the language 25 | var profinetInterfaceName = culture.TwoLetterISOLanguageName.ToLowerInvariant() switch 26 | { 27 | "de" => "PROFINET-Schnittstelle", 28 | "en" => "PROFINET interface", 29 | _ => "PROFINET interface" // Default to English if language is not German or English 30 | }; 31 | 32 | //Set Ip Address: 33 | var node = device.NetworkInterfaces().Single(n => 34 | n.InterfaceType == NetType.Ethernet && n.TryGetAttribute("TypeName", out string typeName) && 35 | typeName == profinetInterfaceName).Nodes.First(); 36 | node.SetAttribute("Address", "192.168.0.15"); 37 | 38 | //Change PG/PC interface: 39 | var onlineProvider = device.HeadModule().AsOnlineProvider(); 40 | 41 | var pn = onlineProvider.Configuration.Modes.First(); 42 | var pcInterfaces = pn.PcInterfaces; 43 | 44 | var chosenPcInterface = pcInterfaces.First(); //i => i.Name.Contains("Intel(R) Ethernet")); 45 | var chosenTargetInterface = 46 | chosenPcInterface.TargetInterfaces.Single(x => x.Name == "CU X127"); 47 | 48 | onlineProvider.Configuration.ApplyConfiguration(chosenTargetInterface); 49 | } 50 | 51 | [Test] 52 | public void PLC_S120Connection() 53 | { 54 | var project = Project; 55 | 56 | var plc = project.Devices.CreateWithItem("OrderNumber:6ES7 515-2UM01-0AB0/V2.9", "", ""); 57 | var s120 = project.Devices.CreateWithItem("OrderNumber:6SL3040-1MA01-0Axx/V5.2.3/S120", "", ""); 58 | 59 | //Get NetworkInterface for plc and s120 (here the first profinet interface) 60 | var networkInterfacePlc = plc.DeviceItems.First(x => x.Classification == DeviceItemClassifications.CPU) 61 | .ProfinetInterfaces().First().GetService(); 62 | 63 | var networkInterfaces120 = s120.HeadModule().ProfinetInterfaces().First().GetService(); 64 | 65 | //Get the nodes for connection of the subnet 66 | var s120Node = networkInterfaces120.Nodes.First(); 67 | var plcNode = networkInterfacePlc.Nodes.First(); 68 | 69 | //Code if profinet interface from plc is already connected to subnet 70 | var plcSubnet = plcNode.ConnectedSubnet; 71 | 72 | //If not connected, create subnet 73 | plcSubnet ??= plcNode.CreateAndConnectToSubnet("TestSubnet"); 74 | 75 | //ConnectToASubnet 76 | s120Node.ConnectToSubnet(plcSubnet); 77 | 78 | 79 | //Get IoConnector for connection of the io system 80 | var ioConnectors120 = networkInterfaces120.IoConnectors.First(); 81 | 82 | //Code if profinet interface from plc is already connected to ioSystem 83 | //If not connected, create ioSystem 84 | var plcIoSystem = networkInterfacePlc.IoControllers.First().IoSystem ?? 85 | networkInterfacePlc.IoControllers.First().CreateIoSystem("TestIOSystem"); 86 | 87 | //Connect ioSystem from s120 88 | ioConnectors120.ConnectToIoSystem(plcIoSystem); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.1.31911.260 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TiaPortal.Openness.CodeSnippets.Plain.Step7", "TiaPortal.Openness.CodeSnippets.Plain.Step7\TiaPortal.Openness.CodeSnippets.Plain.Step7.csproj", "{C6CC04FB-D1F4-4828-845D-8283C2AE4286}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{21A97A04-F736-4CE7-8AE0-A67CE999866E}" 8 | ProjectSection(SolutionItems) = preProject 9 | ..\.editorconfig = ..\.editorconfig 10 | ..\.gitignore = ..\.gitignore 11 | ..\Directory.Build.props = ..\Directory.Build.props 12 | ..\Directory.Build.targets = ..\Directory.Build.targets 13 | ..\nuget.config = ..\nuget.config 14 | ..\README.md = ..\README.md 15 | EndProjectSection 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TiaPortal.Openness.CodeSnippets.WithExtensions.Step7", "TiaPortal.Openness.CodeSnippets.WithExtensions.Step7\TiaPortal.Openness.CodeSnippets.WithExtensions.Step7.csproj", "{CF5A677C-2406-4B06-BDD4-9E2E057BB6D1}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TiaPortal.Openness.CodeSnippets.Plain.Startdrive", "TiaPortal.Openness.CodeSnippets.Plain.Startdrive\TiaPortal.Openness.CodeSnippets.Plain.Startdrive.csproj", "{D1A4BFC7-18EA-445D-8F6A-FE5E7A6AA24D}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc", "TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc\TiaPortal.Openness.CodeSnippets.Plain.Startdrive.Dcc.csproj", "{90D31863-95EB-4CBF-ADCF-0F7192623DAE}" 22 | EndProject 23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive", "TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive\TiaPortal.Openness.CodeSnippets.WithExtensions.Startdrive.csproj", "{C3191D3B-8179-4A1A-B676-68FB09BCFD8D}" 24 | EndProject 25 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TiaPortal.Openness.CodeSnippets.WithExtensions.Setup", "TiaPortal.Openness.CodeSnippets.WithExtensions.Setup\TiaPortal.Openness.CodeSnippets.WithExtensions.Setup.csproj", "{64D26015-EAC3-46BB-BD76-E54A66AC8D27}" 26 | EndProject 27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TiaPortal.Openness.CodeSnippets.Plain.Setup", "TiaPortal.Openness.CodeSnippets.Plain.Setup\TiaPortal.Openness.CodeSnippets.Plain.Setup.csproj", "{4622A3F9-68FB-4B72-97A6-E73DE1B38BCD}" 28 | EndProject 29 | Global 30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 31 | Debug|Any CPU = Debug|Any CPU 32 | Release|Any CPU = Release|Any CPU 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {C6CC04FB-D1F4-4828-845D-8283C2AE4286}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {C6CC04FB-D1F4-4828-845D-8283C2AE4286}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {C6CC04FB-D1F4-4828-845D-8283C2AE4286}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {C6CC04FB-D1F4-4828-845D-8283C2AE4286}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {CF5A677C-2406-4B06-BDD4-9E2E057BB6D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {CF5A677C-2406-4B06-BDD4-9E2E057BB6D1}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {CF5A677C-2406-4B06-BDD4-9E2E057BB6D1}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {CF5A677C-2406-4B06-BDD4-9E2E057BB6D1}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {D1A4BFC7-18EA-445D-8F6A-FE5E7A6AA24D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {D1A4BFC7-18EA-445D-8F6A-FE5E7A6AA24D}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {D1A4BFC7-18EA-445D-8F6A-FE5E7A6AA24D}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {D1A4BFC7-18EA-445D-8F6A-FE5E7A6AA24D}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {90D31863-95EB-4CBF-ADCF-0F7192623DAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {90D31863-95EB-4CBF-ADCF-0F7192623DAE}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {90D31863-95EB-4CBF-ADCF-0F7192623DAE}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {90D31863-95EB-4CBF-ADCF-0F7192623DAE}.Release|Any CPU.Build.0 = Release|Any CPU 51 | {C3191D3B-8179-4A1A-B676-68FB09BCFD8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {C3191D3B-8179-4A1A-B676-68FB09BCFD8D}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {C3191D3B-8179-4A1A-B676-68FB09BCFD8D}.Release|Any CPU.ActiveCfg = Release|Any CPU 54 | {C3191D3B-8179-4A1A-B676-68FB09BCFD8D}.Release|Any CPU.Build.0 = Release|Any CPU 55 | {64D26015-EAC3-46BB-BD76-E54A66AC8D27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 56 | {64D26015-EAC3-46BB-BD76-E54A66AC8D27}.Debug|Any CPU.Build.0 = Debug|Any CPU 57 | {64D26015-EAC3-46BB-BD76-E54A66AC8D27}.Release|Any CPU.ActiveCfg = Release|Any CPU 58 | {64D26015-EAC3-46BB-BD76-E54A66AC8D27}.Release|Any CPU.Build.0 = Release|Any CPU 59 | {4622A3F9-68FB-4B72-97A6-E73DE1B38BCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 60 | {4622A3F9-68FB-4B72-97A6-E73DE1B38BCD}.Debug|Any CPU.Build.0 = Debug|Any CPU 61 | {4622A3F9-68FB-4B72-97A6-E73DE1B38BCD}.Release|Any CPU.ActiveCfg = Release|Any CPU 62 | {4622A3F9-68FB-4B72-97A6-E73DE1B38BCD}.Release|Any CPU.Build.0 = Release|Any CPU 63 | EndGlobalSection 64 | GlobalSection(SolutionProperties) = preSolution 65 | HideSolutionNode = FALSE 66 | EndGlobalSection 67 | GlobalSection(ExtensibilityGlobals) = postSolution 68 | SolutionGuid = {3ED83BFA-D269-4240-90EE-F60905E6CB0D} 69 | EndGlobalSection 70 | EndGlobal 71 | -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/ProgramBlocks/ProgramBlockSnippets.cs: -------------------------------------------------------------------------------- 1 | // © Siemens 2025 2 | // Licensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 3 | 4 | using System.Security; 5 | using NUnit.Framework; 6 | using Siemens.Engineering; 7 | using Siemens.Engineering.Compiler; 8 | using Siemens.Engineering.HW; 9 | using Siemens.Engineering.HW.Features; 10 | using Siemens.Engineering.SW; 11 | using Siemens.Engineering.SW.Blocks; 12 | using TiaPortal.Openness.CodeSnippets.Plain.Setup; 13 | 14 | namespace TiaPortal.Openness.CodeSnippets.Plain.Step7.PLC.ProgramBlocks; 15 | 16 | [TestFixture("Step7.zap20")] 17 | public class ProgramBlockSnippets(string tiaArchiveName) : BaseClass(tiaArchiveName) 18 | { 19 | [SetUp] 20 | public void Setup() 21 | { 22 | var softwareContainer = Project.Devices 23 | .First(x => x.Name.Equals("PLC_S120Democase")) 24 | .DeviceItems 25 | .First(x => x.Classification.Equals(DeviceItemClassifications.CPU)).GetService(); 26 | 27 | if (softwareContainer.Software is null) 28 | { 29 | throw new InvalidOperationException( 30 | "The software container for device 'PLC_S120Democase' does not contain any software instance (null)." 31 | ); 32 | } 33 | 34 | if (softwareContainer.Software is not PlcSoftware software) 35 | { 36 | throw new InvalidOperationException( 37 | $"The software container for device 'PLC_S120Democase' contains a software instance of type '{softwareContainer.Software.GetType().FullName}', but a PlcSoftware was expected." 38 | ); 39 | } 40 | 41 | _blockComposition = software.BlockGroup.Blocks; 42 | } 43 | 44 | // _blockComposition is initialized in the Setup method. 45 | // The Setup method will be run before each test method. 46 | private PlcBlockComposition? _blockComposition; 47 | 48 | [Test] 49 | [TestCase(@"PLC\ProgramBlocks\Resources\PLCBlocks", 50 | new[] { "Block_1", "Block_2", "Block_3", "Block_4", "Block_5" })] 51 | public void ImportProgramBlockComposition(string relativeImportFolderPath, string[] editedBlockNamesArray) 52 | { 53 | var importFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativeImportFolderPath); 54 | HashSet editedBlockNames = new(editedBlockNamesArray); 55 | List blocksToImport = []; 56 | 57 | if (_blockComposition == null) 58 | { 59 | Console.WriteLine("No Block composition"); 60 | return; 61 | } 62 | 63 | blocksToImport.AddRange(_blockComposition.Where(plcBlock => 64 | editedBlockNames.Contains(plcBlock.Name) && !plcBlock.IsKnowHowProtected)); 65 | 66 | Parallel.ForEach(blocksToImport, plcBlock => 67 | { 68 | var blockName = plcBlock.Name; 69 | var filePath = Path.Combine(importFolderPath, blockName); 70 | 71 | // _blockComposition is initialized in the Setup method. 72 | // The Setup method will be run before each test method. 73 | _blockComposition.Import(new FileInfo(filePath), ImportOptions.Override); 74 | editedBlockNames.Remove(blockName); 75 | }); 76 | } 77 | 78 | [Test] 79 | [TestCase(@"PLC\ProgramBlocks\Resources\PLCBlocks", 80 | "Block_Merged")] 81 | public void ImportMergedProgramBlockComposition(string relativeImportFolderPath, string blockName) 82 | { 83 | var importFolderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativeImportFolderPath); 84 | var filePath = Path.Combine(importFolderPath, blockName); 85 | 86 | // _blockComposition is initialized in the Setup method. 87 | // The Setup method will be run before each test method. 88 | _blockComposition?.Import(new FileInfo(filePath), ImportOptions.Override); 89 | } 90 | 91 | [Test] 92 | public void ExportProgramBlock() 93 | { 94 | FileInfo fileInfo = new(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString())); 95 | 96 | // _blockComposition is initialized in the Setup method. 97 | // The Setup method will be run before each test method. 98 | var block = _blockComposition.First(b => b.Name == "Axis_blue"); 99 | var compiler = block?.GetService(); 100 | var result = compiler?.Compile(); 101 | 102 | Console.WriteLine($"Compilation succeeded: {result?.ErrorCount == 0}"); 103 | 104 | block?.Export(fileInfo, ExportOptions.None); 105 | 106 | Console.WriteLine($"File exists: {fileInfo.Exists}"); 107 | 108 | fileInfo.Delete(); 109 | } 110 | 111 | [Test] 112 | public void ProtectPlcBlock() 113 | { 114 | // _blockComposition is initialized in the Setup method. 115 | // The Setup method will be run before each test method. 116 | var block = _blockComposition?.First(b => b.Name == "Axis_blue"); 117 | var plcBlockProtectionProvider = block?.GetService(); 118 | 119 | // Get invalid password characters 120 | var invalidChars = plcBlockProtectionProvider?.GetInvalidPasswordCharacters().ToList(); 121 | var validPassword = "@ValidPassword123"; 122 | 123 | var passwordIsValid = ValidatePassword(validPassword, invalidChars); 124 | if (passwordIsValid) 125 | { 126 | var secureValidPassword = CreateSecureString(validPassword); 127 | plcBlockProtectionProvider?.Protect(secureValidPassword); 128 | } 129 | else 130 | { 131 | Console.WriteLine("Password is invalid"); 132 | } 133 | } 134 | 135 | private static SecureString CreateSecureString(string password) 136 | { 137 | var securePassword = new SecureString(); 138 | foreach (var c in password) 139 | { 140 | securePassword.AppendChar(c); 141 | } 142 | 143 | securePassword.MakeReadOnly(); 144 | return securePassword; 145 | } 146 | 147 | private static bool ValidatePassword(string password, List invalidChars) 148 | { 149 | //The password requirements: 150 | // The password must be at least 8 characters long. 151 | // The password must not exceed the maximum permissible length of 120 characters. 152 | // The password must contain at least one number. 153 | // The password must contain at least one special character. 154 | // The password must contain at least one lower-case and one upper -case character. 155 | 156 | // Check for invalid characters 157 | if (password.Any(invalidChars.Contains)) 158 | { 159 | return false; 160 | } 161 | 162 | // Check length requirements 163 | if (password.Length < 8 || password.Length > 120) 164 | { 165 | return false; 166 | } 167 | 168 | // Check for at least one number 169 | if (!password.Any(char.IsDigit)) 170 | { 171 | return false; 172 | } 173 | 174 | // Check for at least one lowercase character 175 | if (!password.Any(char.IsLower)) 176 | { 177 | return false; 178 | } 179 | 180 | // Check for at least one uppercase character 181 | if (!password.Any(char.IsUpper)) 182 | { 183 | return false; 184 | } 185 | 186 | // Check for at least one special character (non-alphanumeric) 187 | if (password.All(char.IsLetterOrDigit)) 188 | { 189 | return false; 190 | } 191 | 192 | return true; 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products 2 | ## 1. General information: Software in source code and object code 3 | ### 1.1 Use of the Software 4 | Siemens AG and/or a subsidiary of Siemens AG (“Siemens”) provides You royalty-free container images, application examples, sample code and software development kits (“Software”) through sharing platforms (e.g. GitHub, DockerHub, NuGet, etc.). The Software shall only be used for the development and test of software which can be used with Siemens products (“intended purpose”). The Software is non-binding and makes no claim to completeness or functionality. The Software merely offers help with typical tasks and provides an environment for developing and testing applications and other software. You Yourself are responsible for the proper and safe operation of Your products in accordance with applicable regulations and must also check the function of the results of the Software and customize Your products. Siemens reserves the right to make changes to the Software at any time without notice. Software may be provided in object code and/or source code format. Unless explicitly granted in the open source license according to article 2, You shall not decompile, translate, extract, modify or distribute the Software. 5 | ### 1.2 Security information 6 | Siemens provides products and solutions with industrial security functions that support the secure operation of plants, systems, machines and networks. 7 | In order to protect plants, systems, machines and networks against cyber threats, it is necessary to implement – and continuously maintain – a holistic, state-of-the-art industrial security concept. Siemens’ products and solutions constitute one element of such a concept. 8 | Customers are responsible for preventing unauthorized access to their plants, systems, machines and networks. Such systems, machines and components should only be connected to an enterprise network or the internet if and to the extent such a connection is necessary and only when appropriate security measures (e.g. firewalls and/or network segmentation) are in place. 9 | For additional information on industrial security measures that may be implemented, please visit https://www.siemens.com/industrialsecurity. 10 | ### 1.3 Compliance with Export Control Regulations 11 | You shall comply with all applicable sanctions, embargoes and (re-)export control regulations, and, in any event, with those of the European Union and the United States of America (collectively “Export Regulations”). In particular, the information, software and documentation provided by Siemens (collectively “Licensed Material”) shall not be used, accessed or transferred, unless permitted by the Export Regulations or respective governmental licenses or approvals, (i) in or to any location prohibited by or subject to comprehensive sanctions (currently Russia, Cuba, Iran, North Korea, Syria, and the Crimea region of Ukraine, Donetsk and Luhansk regions of Ukraine) or license requirements according to the Export Regulations; (ii) by or to any individual or entity designated on a sanctioned party list of the Export Regulations; (iii) for any purpose prohibited by the Export Regulations (e.g. use in connection with armaments, nuclear technology or weapons); or (iv) to upload any content unless it is noncontrolled (e .g. in the EU: AL = N; in the U.S.: ECCN = N or EAR99). If required to enable authorities or Siemens to conduct export control checks, You, upon request by Siemens, shall promptly provide Siemens with all information pertaining to You, the intended use and the location of use of the Licensed Material. Siemens shall not be obligated to fulfill this Agreement if such fulfillment is prevented by any impediments arising out of national or international foreign trade or customs requirements or any embargoes or other sanctions. 12 | ## 2. Open Source License for Software in source code and generated source code 13 | In case the Software contains or generates source code the following open source license shall apply 14 | for such source code: 15 | 16 | MIT License 17 | 18 | Copyright 2025 Siemens AG 19 | 20 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | ## 3. Software provided in object code 26 | For all portions of the Software that are provided in object code format the following conditions shall apply (“Royalty-Free Siemens Software Conditions”): 27 | ### 3.1 License Grant 28 | Siemens grants You the royalty-free, non-exclusive, non-sublicensable and non-transferable right to use, have used the Software by technically trained personnel and for the intended purpose only. 29 | ### 3.2 Included third-party software components 30 | Insofar as Open Source Software is included in the Software, such Open Source Software is listed in the Readme_OSS file of the Software. You are entitled to use the Open Source Software in accordance with the respective applicable license conditions of the Open Source Software. These OSS license conditions are included with Software and shall prevail over these Royalty-Free Siemens Software Conditions. The Open Source Software license conditions shall have priority also in relation to the proprietary Siemens components insofar as the Open Source Software license conditions grant You certain rights of use on the basis of the connection of OSS components with proprietary Siemens components. 31 | 32 | Siemens shall make available to You, at Your request, the Open Source Software source code in return for payment of a fee to compensate for expenses insofar as the license conditions of the Open Source Software require such release of the source code. 33 | 34 | The Software may, in addition to Open Source Software, contain other licensed software, i.e. software which was not developed by Siemens itself, but which Siemens has obtained from third parties, e.g. Microsoft Ireland Operations Ltd, under a license. If You shall receive in such case the conditions of the respective licensor of the licensed software in the Readme_OSS file, these shall apply to the liability of the licensor in relation to You. In terms of the liability of Siemens to You, these Royalty-Free Siemens Software Conditions shall apply in each case. 35 | ### 3.3 Disclaimer of liability 36 | Siemens shall not assume any liability, for any legal reason whatsoever, including, without limitation, liability for the usability, availability, completeness and freedom from defects of the Software as well as for the Licensed Material and any damage caused thereby. This shall not apply in cases of mandatory liability, for example product liability law or in cases of intent, gross negligence, or culpable loss of life, bodily injury or damage to health, non-compliance with a guarantee, fraudulent non-disclosure of a defect, or culpable breach of material contractual obligations. Claims for damages arising from a breach of material contractual obligations shall however be limited to the foreseeable damage typical of the type of agreement, unless liability arises from intent or gross negligence or is based on loss of life, bodily injury or damage to health. The foregoing provisions do not imply any change in the burden of proof to Your detriment. You shall indemnify Siemens against existing or future claims of third parties in this connection except where Siemens is mandatorily liable. 37 | 38 | By using the Software and the Licensed Material, You acknowledge that Siemens cannot be held liable for any damage beyond the liability provisions described. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | # but not Directory.Build.rsp, as it configures directory-level build defaults 86 | !Directory.Build.rsp 87 | *.sbr 88 | *.tlb 89 | *.tli 90 | *.tlh 91 | *.tmp 92 | *.tmp_proj 93 | *_wpftmp.csproj 94 | *.log 95 | *.tlog 96 | *.vspscc 97 | *.vssscc 98 | .builds 99 | *.pidb 100 | *.svclog 101 | *.scc 102 | 103 | # Chutzpah Test files 104 | _Chutzpah* 105 | 106 | # Visual C++ cache files 107 | ipch/ 108 | *.aps 109 | *.ncb 110 | *.opendb 111 | *.opensdf 112 | *.sdf 113 | *.cachefile 114 | *.VC.db 115 | *.VC.VC.opendb 116 | 117 | # Visual Studio profiler 118 | *.psess 119 | *.vsp 120 | *.vspx 121 | *.sap 122 | 123 | # Visual Studio Trace Files 124 | *.e2e 125 | 126 | # TFS 2012 Local Workspace 127 | $tf/ 128 | 129 | # Guidance Automation Toolkit 130 | *.gpState 131 | 132 | # ReSharper is a .NET coding add-in 133 | _ReSharper*/ 134 | *.[Rr]e[Ss]harper 135 | *.DotSettings.user 136 | 137 | # TeamCity is a build add-in 138 | _TeamCity* 139 | 140 | # DotCover is a Code Coverage Tool 141 | *.dotCover 142 | 143 | # AxoCover is a Code Coverage Tool 144 | .axoCover/* 145 | !.axoCover/settings.json 146 | 147 | # Coverlet is a free, cross platform Code Coverage Tool 148 | coverage*.json 149 | coverage*.xml 150 | coverage*.info 151 | 152 | # Visual Studio code coverage results 153 | *.coverage 154 | *.coveragexml 155 | 156 | # NCrunch 157 | _NCrunch_* 158 | .*crunch*.local.xml 159 | nCrunchTemp_* 160 | 161 | # MightyMoose 162 | *.mm.* 163 | AutoTest.Net/ 164 | 165 | # Web workbench (sass) 166 | .sass-cache/ 167 | 168 | # Installshield output folder 169 | [Ee]xpress/ 170 | 171 | # DocProject is a documentation generator add-in 172 | DocProject/buildhelp/ 173 | DocProject/Help/*.HxT 174 | DocProject/Help/*.HxC 175 | DocProject/Help/*.hhc 176 | DocProject/Help/*.hhk 177 | DocProject/Help/*.hhp 178 | DocProject/Help/Html2 179 | DocProject/Help/html 180 | 181 | # Click-Once directory 182 | publish/ 183 | 184 | # Publish Web Output 185 | *.[Pp]ublish.xml 186 | *.azurePubxml 187 | # Note: Comment the next line if you want to checkin your web deploy settings, 188 | # but database connection strings (with potential passwords) will be unencrypted 189 | *.pubxml 190 | *.publishproj 191 | 192 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 193 | # checkin your Azure Web App publish settings, but sensitive information contained 194 | # in these scripts will be unencrypted 195 | PublishScripts/ 196 | 197 | # NuGet Packages 198 | *.nupkg 199 | # NuGet Symbol Packages 200 | *.snupkg 201 | # The packages folder can be ignored because of Package Restore 202 | **/[Pp]ackages/* 203 | # except build/, which is used as an MSBuild target. 204 | !**/[Pp]ackages/build/ 205 | # Uncomment if necessary however generally it will be regenerated when needed 206 | #!**/[Pp]ackages/repositories.config 207 | # NuGet v3's project.json files produces more ignorable files 208 | *.nuget.props 209 | *.nuget.targets 210 | 211 | # Microsoft Azure Build Output 212 | csx/ 213 | *.build.csdef 214 | 215 | # Microsoft Azure Emulator 216 | ecf/ 217 | rcf/ 218 | 219 | # Windows Store app package directories and files 220 | AppPackages/ 221 | BundleArtifacts/ 222 | Package.StoreAssociation.xml 223 | _pkginfo.txt 224 | *.appx 225 | *.appxbundle 226 | *.appxupload 227 | 228 | # Visual Studio cache files 229 | # files ending in .cache can be ignored 230 | *.[Cc]ache 231 | # but keep track of directories ending in .cache 232 | !?*.[Cc]ache/ 233 | 234 | # Others 235 | ClientBin/ 236 | ~$* 237 | *~ 238 | *.dbmdl 239 | *.dbproj.schemaview 240 | *.jfm 241 | *.pfx 242 | *.publishsettings 243 | orleans.codegen.cs 244 | 245 | # Including strong name files can present a security risk 246 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 247 | #*.snk 248 | 249 | # Since there are multiple workflows, uncomment next line to ignore bower_components 250 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 251 | #bower_components/ 252 | 253 | # RIA/Silverlight projects 254 | Generated_Code/ 255 | 256 | # Backup & report files from converting an old project file 257 | # to a newer Visual Studio version. Backup files are not needed, 258 | # because we have git ;-) 259 | _UpgradeReport_Files/ 260 | Backup*/ 261 | UpgradeLog*.XML 262 | UpgradeLog*.htm 263 | ServiceFabricBackup/ 264 | *.rptproj.bak 265 | 266 | # SQL Server files 267 | *.mdf 268 | *.ldf 269 | *.ndf 270 | 271 | # Business Intelligence projects 272 | *.rdl.data 273 | *.bim.layout 274 | *.bim_*.settings 275 | *.rptproj.rsuser 276 | *- [Bb]ackup.rdl 277 | *- [Bb]ackup ([0-9]).rdl 278 | *- [Bb]ackup ([0-9][0-9]).rdl 279 | 280 | # Microsoft Fakes 281 | FakesAssemblies/ 282 | 283 | # GhostDoc plugin setting file 284 | *.GhostDoc.xml 285 | 286 | # Node.js Tools for Visual Studio 287 | .ntvs_analysis.dat 288 | node_modules/ 289 | 290 | # Visual Studio 6 build log 291 | *.plg 292 | 293 | # Visual Studio 6 workspace options file 294 | *.opt 295 | 296 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 297 | *.vbw 298 | 299 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 300 | *.vbp 301 | 302 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 303 | *.dsw 304 | *.dsp 305 | 306 | # Visual Studio 6 technical files 307 | *.ncb 308 | *.aps 309 | 310 | # Visual Studio LightSwitch build output 311 | **/*.HTMLClient/GeneratedArtifacts 312 | **/*.DesktopClient/GeneratedArtifacts 313 | **/*.DesktopClient/ModelManifest.xml 314 | **/*.Server/GeneratedArtifacts 315 | **/*.Server/ModelManifest.xml 316 | _Pvt_Extensions 317 | 318 | # Paket dependency manager 319 | .paket/paket.exe 320 | paket-files/ 321 | 322 | # FAKE - F# Make 323 | .fake/ 324 | 325 | # CodeRush personal settings 326 | .cr/personal 327 | 328 | # Python Tools for Visual Studio (PTVS) 329 | __pycache__/ 330 | *.pyc 331 | 332 | # Cake - Uncomment if you are using it 333 | # tools/** 334 | # !tools/packages.config 335 | 336 | # Tabs Studio 337 | *.tss 338 | 339 | # Telerik's JustMock configuration file 340 | *.jmconfig 341 | 342 | # BizTalk build output 343 | *.btp.cs 344 | *.btm.cs 345 | *.odx.cs 346 | *.xsd.cs 347 | 348 | # OpenCover UI analysis results 349 | OpenCover/ 350 | 351 | # Azure Stream Analytics local run output 352 | ASALocalRun/ 353 | 354 | # MSBuild Binary and Structured Log 355 | *.binlog 356 | 357 | # NVidia Nsight GPU debugger configuration file 358 | *.nvuser 359 | 360 | # MFractors (Xamarin productivity tool) working folder 361 | .mfractor/ 362 | 363 | # Local History for Visual Studio 364 | .localhistory/ 365 | 366 | # Visual Studio History (VSHistory) files 367 | .vshistory/ 368 | 369 | # BeatPulse healthcheck temp database 370 | healthchecksdb 371 | 372 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 373 | MigrationBackup/ 374 | 375 | # Ionide (cross platform F# VS Code tools) working folder 376 | .ionide/ 377 | 378 | # Fody - auto-generated XML schema 379 | FodyWeavers.xsd 380 | 381 | # VS Code files for those working on multiple tools 382 | .vscode/* 383 | !.vscode/settings.json 384 | !.vscode/tasks.json 385 | !.vscode/launch.json 386 | !.vscode/extensions.json 387 | *.code-workspace 388 | 389 | # Local History for Visual Studio Code 390 | .history/ 391 | 392 | # Windows Installer files from build outputs 393 | *.cab 394 | *.msi 395 | *.msix 396 | *.msm 397 | *.msp 398 | 399 | # JetBrains Rider 400 | *.sln.iml -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Don't use tabs for indentation. 7 | [*] 8 | indent_style = space 9 | # (Please don't specify an indent_size here; that has too many unintended consequences.) 10 | spelling_exclusion_path = SpellingExclusions.dic 11 | 12 | # Code files 13 | [*.{cs,csx,vb,vbx}] 14 | indent_size = 4 15 | insert_final_newline = true 16 | charset = utf-8-bom 17 | 18 | # XML project files 19 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] 20 | indent_size = 2 21 | 22 | # XML config files 23 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] 24 | indent_size = 2 25 | 26 | # JSON files 27 | [*.json] 28 | indent_size = 2 29 | 30 | # Powershell files 31 | [*.ps1] 32 | indent_size = 2 33 | 34 | # Shell script files 35 | [*.sh] 36 | end_of_line = lf 37 | indent_size = 2 38 | 39 | # Dotnet code style settings: 40 | [*.{cs,vb}] 41 | 42 | # Sort using and Import directives with System.* appearing first 43 | dotnet_sort_system_directives_first = true 44 | dotnet_separate_import_directive_groups = false 45 | # Avoid "this." and "Me." if not necessary 46 | dotnet_style_qualification_for_field = false:refactoring 47 | dotnet_style_qualification_for_property = false:refactoring 48 | dotnet_style_qualification_for_method = false:refactoring 49 | dotnet_style_qualification_for_event = false:refactoring 50 | 51 | # Use language keywords instead of framework type names for type references 52 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 53 | dotnet_style_predefined_type_for_member_access = true:suggestion 54 | 55 | # Suggest more modern language features when available 56 | dotnet_style_object_initializer = true:suggestion 57 | dotnet_style_collection_initializer = true:suggestion 58 | dotnet_style_coalesce_expression = true:suggestion 59 | dotnet_style_null_propagation = true:suggestion 60 | dotnet_style_explicit_tuple_names = true:suggestion 61 | 62 | # Whitespace options 63 | dotnet_style_allow_multiple_blank_lines_experimental = false 64 | 65 | # Non-private static fields are PascalCase 66 | dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion 67 | dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields 68 | dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style 69 | 70 | dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field 71 | dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected 72 | dotnet_naming_symbols.non_private_static_fields.required_modifiers = static 73 | 74 | dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case 75 | 76 | # Non-private readonly fields are PascalCase 77 | dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion 78 | dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields 79 | dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style 80 | 81 | dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field 82 | dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected 83 | dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly 84 | 85 | dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case 86 | 87 | # Constants are PascalCase 88 | dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion 89 | dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants 90 | dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style 91 | 92 | dotnet_naming_symbols.constants.applicable_kinds = field, local 93 | dotnet_naming_symbols.constants.required_modifiers = const 94 | 95 | dotnet_naming_style.constant_style.capitalization = pascal_case 96 | 97 | # Static fields are camelCase and start with s_ 98 | dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion 99 | dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields 100 | dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style 101 | 102 | dotnet_naming_symbols.static_fields.applicable_kinds = field 103 | dotnet_naming_symbols.static_fields.required_modifiers = static 104 | 105 | dotnet_naming_style.static_field_style.capitalization = camel_case 106 | dotnet_naming_style.static_field_style.required_prefix = s_ 107 | 108 | # Instance fields are camelCase and start with _ 109 | dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion 110 | dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields 111 | dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style 112 | 113 | dotnet_naming_symbols.instance_fields.applicable_kinds = field 114 | 115 | dotnet_naming_style.instance_field_style.capitalization = camel_case 116 | dotnet_naming_style.instance_field_style.required_prefix = _ 117 | 118 | # Locals and parameters are camelCase 119 | dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion 120 | dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters 121 | dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style 122 | 123 | dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local 124 | 125 | dotnet_naming_style.camel_case_style.capitalization = camel_case 126 | 127 | # Local functions are PascalCase 128 | dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion 129 | dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions 130 | dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style 131 | 132 | dotnet_naming_symbols.local_functions.applicable_kinds = local_function 133 | 134 | dotnet_naming_style.local_function_style.capitalization = pascal_case 135 | 136 | # By default, name items with PascalCase 137 | dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion 138 | dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members 139 | dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style 140 | 141 | dotnet_naming_symbols.all_members.applicable_kinds = * 142 | 143 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case 144 | 145 | # RS0016: Only enable if API files are present 146 | dotnet_public_api_analyzer.require_api_files = true 147 | 148 | # IDE0055: Fix formatting 149 | # Workaround for https://github.com/dotnet/roslyn/issues/70570 150 | dotnet_diagnostic.IDE0055.severity = warning 151 | 152 | # https://github.com/dotnet/roslyn-analyzers/issues/7436 - False positives from valid GetDeclaredSymbol calls 153 | dotnet_diagnostic.RS1039.severity = none 154 | 155 | # These xUnit analyzers were disabled temporarily to let us move to the 156 | # new xUnit and get past several component governance issues. The 157 | # following issue tracks enabling them 158 | # 159 | # https://github.com/dotnet/roslyn/issues/75093 160 | dotnet_diagnostic.xUnit1012.severity = none 161 | dotnet_diagnostic.xUnit1030.severity = none 162 | dotnet_diagnostic.xUnit1031.severity = none 163 | dotnet_diagnostic.xUnit2005.severity = none 164 | dotnet_diagnostic.xUnit2020.severity = none 165 | dotnet_diagnostic.xUnit2023.severity = none 166 | dotnet_diagnostic.xUnit2029.severity = none 167 | 168 | # CSharp code style settings: 169 | [*.cs] 170 | file_header_template = © Siemens 2025\nLicensed under: "Royalty-free Software provided by Siemens on sharing platforms for developers/users of Siemens products". See LICENSE.md. 171 | dotnet_diagnostic.IDE0073.severity = warning 172 | 173 | # Newline settings 174 | csharp_new_line_before_open_brace = all 175 | csharp_new_line_before_else = true 176 | csharp_new_line_before_catch = true 177 | csharp_new_line_before_finally = true 178 | csharp_new_line_before_members_in_object_initializers = true 179 | csharp_new_line_before_members_in_anonymous_types = true 180 | csharp_new_line_between_query_expression_clauses = true 181 | 182 | # Indentation preferences 183 | csharp_indent_block_contents = true 184 | csharp_indent_braces = false 185 | csharp_indent_case_contents = true 186 | csharp_indent_case_contents_when_block = true 187 | csharp_indent_switch_labels = true 188 | csharp_indent_labels = flush_left 189 | 190 | # Whitespace options 191 | csharp_style_allow_embedded_statements_on_same_line_experimental = false 192 | csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false 193 | csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false 194 | csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false 195 | csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false 196 | 197 | # Prefer "var" everywhere 198 | csharp_style_var_for_built_in_types = true:suggestion 199 | csharp_style_var_when_type_is_apparent = true:suggestion 200 | csharp_style_var_elsewhere = true:suggestion 201 | 202 | # Prefer method-like constructs to have a block body 203 | csharp_style_expression_bodied_methods = false:none 204 | csharp_style_expression_bodied_constructors = false:none 205 | csharp_style_expression_bodied_operators = false:none 206 | 207 | # Prefer property-like constructs to have an expression-body 208 | csharp_style_expression_bodied_properties = true:none 209 | csharp_style_expression_bodied_indexers = true:none 210 | csharp_style_expression_bodied_accessors = true:none 211 | 212 | # Suggest more modern language features when available 213 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 214 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 215 | csharp_style_inlined_variable_declaration = true:suggestion 216 | csharp_style_throw_expression = true:suggestion 217 | csharp_style_conditional_delegate_call = true:suggestion 218 | csharp_style_prefer_extended_property_pattern = true:suggestion 219 | 220 | # Space preferences 221 | csharp_space_after_cast = false 222 | csharp_space_after_colon_in_inheritance_clause = true 223 | csharp_space_after_comma = true 224 | csharp_space_after_dot = false 225 | csharp_space_after_keywords_in_control_flow_statements = true 226 | csharp_space_after_semicolon_in_for_statement = true 227 | csharp_space_around_binary_operators = before_and_after 228 | csharp_space_around_declaration_statements = do_not_ignore 229 | csharp_space_before_colon_in_inheritance_clause = true 230 | csharp_space_before_comma = false 231 | csharp_space_before_dot = false 232 | csharp_space_before_open_square_brackets = false 233 | csharp_space_before_semicolon_in_for_statement = false 234 | csharp_space_between_empty_square_brackets = false 235 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 236 | csharp_space_between_method_call_name_and_opening_parenthesis = false 237 | csharp_space_between_method_call_parameter_list_parentheses = false 238 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 239 | csharp_space_between_method_declaration_name_and_open_parenthesis = false 240 | csharp_space_between_method_declaration_parameter_list_parentheses = false 241 | csharp_space_between_parentheses = false 242 | csharp_space_between_square_brackets = false 243 | 244 | # Blocks are allowed 245 | csharp_prefer_braces = true:silent 246 | csharp_preserve_single_line_blocks = true 247 | csharp_preserve_single_line_statements = true 248 | 249 | # IDE0060: Remove unused parameter 250 | dotnet_diagnostic.IDE0060.severity = warning 251 | 252 | [src/{Compilers,ExpressionEvaluator,Scripting}/**Test**/*.{cs,vb}] 253 | 254 | # IDE0060: Remove unused parameter 255 | dotnet_diagnostic.IDE0060.severity = none 256 | 257 | [src/{Analyzers,CodeStyle,Features,Workspaces,EditorFeatures,VisualStudio}/**/*.{cs,vb}] 258 | 259 | # IDE0011: Add braces 260 | csharp_prefer_braces = when_multiline:warning 261 | # NOTE: We need the below severity entry for Add Braces due to https://github.com/dotnet/roslyn/issues/44201 262 | dotnet_diagnostic.IDE0011.severity = warning 263 | 264 | # IDE0040: Add accessibility modifiers 265 | dotnet_diagnostic.IDE0040.severity = warning 266 | 267 | # IDE0052: Remove unread private member 268 | dotnet_diagnostic.IDE0052.severity = warning 269 | 270 | # IDE0059: Unnecessary assignment to a value 271 | dotnet_diagnostic.IDE0059.severity = warning 272 | 273 | # CA1012: Abstract types should not have public constructors 274 | dotnet_diagnostic.CA1012.severity = warning 275 | 276 | # CA1822: Make member static 277 | dotnet_diagnostic.CA1822.severity = warning 278 | 279 | # Prefer "var" everywhere 280 | dotnet_diagnostic.IDE0007.severity = warning 281 | csharp_style_var_for_built_in_types = true:warning 282 | csharp_style_var_when_type_is_apparent = true:warning 283 | csharp_style_var_elsewhere = true:warning 284 | 285 | # csharp_style_allow_embedded_statements_on_same_line_experimental 286 | dotnet_diagnostic.IDE2001.severity = warning 287 | 288 | # csharp_style_allow_blank_lines_between_consecutive_braces_experimental 289 | dotnet_diagnostic.IDE2002.severity = warning 290 | 291 | # csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental 292 | dotnet_diagnostic.IDE2004.severity = warning 293 | 294 | # csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental 295 | dotnet_diagnostic.IDE2005.severity = warning 296 | 297 | # csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental 298 | dotnet_diagnostic.IDE2006.severity = warning 299 | 300 | [src/{VisualStudio}/**/*.{cs,vb}] 301 | # CA1822: Make member static 302 | # There is a risk of accidentally breaking an internal API that partners rely on though IVT. 303 | dotnet_code_quality.CA1822.api_surface = private 304 | 305 | [**/{ExternalAccess}/**/*.{cs,vb}] 306 | 307 | # RS0016: Only enable if API files are present 308 | dotnet_public_api_analyzer.require_api_files = true 309 | 310 | dotnet_diagnostic.RS0051.severity = error 311 | dotnet_diagnostic.RS0052.severity = error 312 | dotnet_diagnostic.RS0053.severity = error 313 | dotnet_diagnostic.RS0054.severity = error 314 | dotnet_diagnostic.RS0055.severity = error 315 | dotnet_diagnostic.RS0056.severity = error 316 | dotnet_diagnostic.RS0057.severity = error 317 | dotnet_diagnostic.RS0058.severity = error 318 | dotnet_diagnostic.RS0059.severity = error 319 | dotnet_diagnostic.RS0060.severity = error 320 | dotnet_diagnostic.RS0061.severity = error -------------------------------------------------------------------------------- /src/TiaPortal.Openness.CodeSnippets.Plain.Step7/PLC/ProgramBlocks/Resources/PLCBlocks/Block_Merged: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | Optimized 17 | 100 18 | Block_1 19 | 20 | 1 21 | SCL 22 | false 23 | 24 | 25 | 26 | 27 | 28 | 29 | en-US 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | TRUE 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Statement section IF 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | SCL 63 | 64 | 65 | 66 | 67 | 68 | 69 | en-US 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | en-US 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | en-US 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
104 |
105 |
106 |
107 |
108 |
109 | 110 | 111 | Optimized 112 | 100 113 | Block_2 114 | 115 | 1 116 | SCL 117 | false 118 | 119 | 120 | 121 | 122 | 123 | 124 | en-US 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | TRUE 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | Statement section IF 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | SCL 158 | 159 | 160 | 161 | 162 | 163 | 164 | en-US 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | en-US 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | en-US 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 |
199 |
200 |
201 |
202 |
203 |
204 | 205 | 206 | Optimized 207 | 100 208 | Block_3 209 | 210 | 1 211 | SCL 212 | false 213 | 214 | 215 | 216 | 217 | 218 | 219 | en-US 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | TRUE 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | Statement section IF 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | SCL 253 | 254 | 255 | 256 | 257 | 258 | 259 | en-US 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | en-US 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | en-US 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 |
294 |
295 |
296 |
297 |
298 |
299 | 300 | 301 | Optimized 302 | 100 303 | Block_4 304 | 305 | 1 306 | SCL 307 | false 308 | 309 | 310 | 311 | 312 | 313 | 314 | en-US 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | TRUE 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | Statement section IF 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | SCL 348 | 349 | 350 | 351 | 352 | 353 | 354 | en-US 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | en-US 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | en-US 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 |
389 |
390 |
391 |
392 |
393 |
394 | 395 | 396 | Optimized 397 | 100 398 | Block_5 399 | 400 | 1 401 | SCL 402 | false 403 | 404 | 405 | 406 | 407 | 408 | 409 | en-US 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | TRUE 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | Statement section IF 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | SCL 443 | 444 | 445 | 446 | 447 | 448 | 449 | en-US 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | en-US 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | en-US 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | --------------------------------------------------------------------------------