Service Definition and Types of Services
Each Manager Service API service must have a unique definition within a single project or system.
Various service properties are used to:
- Start and run services on the server
- Correctly address services on the client
All services are distinguished based on the following aspects:
-
System (only on client):
- The name of the WinCC OA system.
- This is implicit information on the server, as the system in which the manager and service are running is known.
- It is an optional argument on the client and is not needed for the 'local' system.
-
Name:
- The service name is the primary identifier to differentiate services.
- It is recommended to use prefixes on the customer side to avoid name collisions with services provided by WinCC OA.
- While the name is used internally in a case-insensitive manner, it is recommended to use PascalCase in the definition.
- Only alphanumeric characters and
/are allowed. This follows theppathdefinition of the URL specification for PROSPERO URLs. - See service suffix examples for how the name is used regularly, and see the manager-specific examples for advanced naming techniques.
- There are two hosting types:
-
Global: The default case. Global Services are intended for situations where the client and the required functionality do not need to know which specific manager is hosting the service. From the client's point of view, the focus is on accessing the service, no matter where it is located. This service behaves as a singleton within a single WinCC OA project. In summary, the scope of global services covers the entire WinCC OA project.
-
Manager-specific: Manager-Specific Services are limited to the scope of a single manager within the project. In this case, the client interacts with a service that is hosted by a particular manager. This structure is useful when you need to deploy the same service on multiple managers, such as manager-specific diagnostic tools or utilities that are specific to each manager or driver. This approach allows each manager to have its own instance of the service, tailored to its individual requirements.
- Service Hosting Manager: This information is implicit on the
server side because the manager type of the service hosting manager
is already known. On the client side, this is a required argument
for manager-specific services, but it is not used for global
services. The following distinctions are made:
- Manager Type: The ManagerType of the service hosting manager.
- Manager Number: The number assigned to the service hosting manager.
- Replica: The replica of the service hosting manager. There
are three possible cases:
- None: No replica is present. For example, this applies to any service in a single system or a global service in a redundant system.
- Left: The logical left (primary) replica in a redundant system.
- Right: The logical right (secondary) replica in a redundant system.
- Service Hosting Manager: This information is implicit on the
server side because the manager type of the service hosting manager
is already known. On the client side, this is a required argument
for manager-specific services, but it is not used for global
services. The following distinctions are made:
-
Manager-specific Services
By default, services are defined as global services. The following code shows how manager-specific services are used.
Example codes for a server: Options objects (CTRL:
VrpcServiceOptions, C++:
::vrpc::ServiceOptions, C#:
VrpcServiceDefinitionOptions, TS:
Vrpc.ServiceOptions) are used to change the defaults. The
following code examples show how this can be achieved.
public void registerManSpecificService(VrpcServiceContainer &serviceContainer, shared_ptr<VrpcServiceBase> &service)
{
VrpcServiceOptions options;
// Register service as manager-specific service
options.withManagerSpecificService();
serviceContainer.registerService(service, options);
} void registerManSpecificService(::vrpc::ServiceContainer& serviceContainer, std::shared_ptr<::vrpc::ServiceBaseBase> service)
{
::vrpc::ServiceOptions options;
// Register service as manager-specific service
options.withManagerSpecificService();
serviceContainer.registerService(service, options);
} public void RegisterManSpecificService<Service>(IServiceCollection services)
where Service : VrpcServiceBase
{
services.AddOaVrpcManagerService<Service>(options =>
{
// Register service as manager-specific service
options.WithManagerSpecificService();
});
} public registerManSpecificService(
serviceContainer: Vrpc.ServiceContainer,
service: Vrpc.ServiceBase,
) {
const options = new Vrpc.ServiceOptions();
// Register service as manager-specific service
options.withManagerSpecificService();
serviceContainer.registerService(service, options);
}Example codes for a client: Options objects (CTRL / C#:
VrpcStubOptions, C++: ::vrpc::StubOptions, TS: Vrpc.StubOptions) are
used to change the default settings. By default, services are addressed as global
services. The following example shows how to address a manager-specific service. In
the example we assume the service is hosted in a CTRL manager with number 1 in a
single system.
public shared_ptr<VrpcStub> createStubForManSpecificService()
{
VrpcStubOptions options = VrpcStubOptions();
// Create a stub for a manager-specific service
options.withManagerSpecificService(CTRL_MAN, 1);
return VrpcStub::createAndInitialize("SomeServiceName", options);
} std::unique_ptr<::vrpc::Stub> createStubForManSpecificService()
{
::vrpc::StubOptions stubOptions;
// Create a stub for a manager-specific service
stubOptions.withManagerSpecificService(CTRL_MAN, 1);
return std::make_unique<::vrpc::Stub>("SomeServiceName", stubOptions);
} public VrpcStub CreateStubForManSpecificService(IOaManager manager)
{
return new VrpcStub(manager, "SomeServiceName", options =>
{
// Create a stub for a manager-specific service
options.WithManagerSpecificService(ManagerIdentifier.OaManagerType.Ctrl, 1);
});
} public createStubForManSpecificService(): Vrpc.Stub {
const options = new Vrpc.StubOptions();
// Create a stub for a manager-specific service
options.withManagerSpecificService(CTRL_MAN, 1);
return new Vrpc.Stub('SomeServiceName', options);
}Service Suffix
The service name is defined in the service implementation and stub declaration. See also How to implement a service and How to implement a client.
In order to use the same service implementation multiple times, it is necessary to have unique names. This can be achieved by using a special suffix option during service registration:
Example codes for a server:
public void registerServiceWithSuffix(VrpcServiceContainer &serviceContainer, shared_ptr<VrpcServiceBase> &service)
{
VrpcServiceOptions options;
// Register service as manager-specific service
options.setServiceNameSuffix("_Some_Suffix");
serviceContainer.registerService(service, options);
} void registerServiceWithSuffix(::vrpc::ServiceContainer& serviceContainer, std::shared_ptr<::vrpc::ServiceBaseBase> service)
{
::vrpc::ServiceOptions options;
// Set service name suffix
options.setServiceNameSuffix("_SomeSuffix");
serviceContainer.registerService(service, options);
} public void RegisterServiceWithSuffix<Service>(IServiceCollection services)
where Service : VrpcServiceBase
{
services.AddOaVrpcManagerService<Service>(options =>
{
// Register service with name suffix
options.ServiceNameSuffix = "_SomeSuffix";
});
} public registerServiceWithSuffix(
serviceContainer: Vrpc.ServiceContainer,
service: Vrpc.ServiceBase,
) {
const options = new Vrpc.ServiceOptions();
// Set service name suffix
options.serviceNameSuffix = '_SomeSuffix';
serviceContainer.registerService(service, options);
} For symmetric behavior, the stub also supports such an option:
Example codes for a client:
public shared_ptr<VrpcStub> createStubWithSuffix()
{
VrpcStubOptions options = VrpcStubOptions();
// Set service name suffix
options.setServiceNameSuffix("_SomeSuffix");
return VrpcStub::createAndInitialize("SomeServiceName", options);
} std::unique_ptr<::vrpc::Stub> createStubWithSuffix()
{
::vrpc::StubOptions stubOptions;
// Set service name suffix
stubOptions.setServiceNameSuffix("_SomeSuffix");
return std::make_unique<::vrpc::Stub>("SomeServiceName", stubOptions);
} public VrpcStub CreateStubWithSuffix(IOaManager manager)
{
return new VrpcStub(manager, "SomeServiceName", options =>
{
// Set service name suffix
options.ServiceNameSuffix = "_SomeSuffix";
});
} public createStubWithSuffix(): Vrpc.Stub {
const options = new Vrpc.StubOptions();
// Set service name suffix
options.serviceNameSuffix = '_SomeSuffix';
return new Vrpc.Stub('SomeServiceName', options);
}