├── 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 | 
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 | 
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 | 
71 |
72 | ---
73 |
74 | ### 2. Installed Step7 + Startdrive
75 |
76 | Use the following solution filter file: [StartdriveProjectSubset.slnf](src/StartdriveProjectSubset.slnf)
77 |
78 | 
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 | 
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 |
--------------------------------------------------------------------------------