Interact with a SiLA Server

Features

When connecting to a SiLA Server, each of the features implemented by the server is added to the SilaClient object as an attribute, registered with the feature identifier. Example: The SiLAService feature is available as SilaClient.SiLAService.

Commands, properties and metadata are attributes of these feature objects, again registered with the feature identifier. Example: The property ImplementedFeatures of the SiLAService feature is available as SilaClient.SiLAService.ImplementedFeatures.

Properties

Properties are represented either by the ClientUnobservableProperty or ClientObservableProperty class. Both have a method get(), which requests the current property value from the connected SiLA Server.

>>> client.GreetingProvider.StartYear.get()  # unobservable property
2022

>>> client.TimerProvider.CurrentTime.get()  # observable property
datetime.time(10, 49, 11, tzinfo=datetime.timezone.utc)

The SiLA specification defines a subscription mechanism for observable properties. Use the method ClientObservableProperty.subscribe to subscribe to an observable property. It will return a Subscription object, which can be used to iterate over the received values, or to add callback functions that are called on each received value.

>>> subscription = client.TimerProvider.CurrentTime.subscribe()

>>> for value in subscription:  # loop runs until calling `subscription.cancel()`
...     print(value)  # print every received value

>>> subscription.add_callback(print)  # print every received value

>>> subscription.cancel()  # cancel subscription

The method ClientUnobservableProperty.subscribe_by_polling emulates such a subscription mechanism by actively polling the current property value from the server.

>>> subscription = client.GreetingProvider.StartYear.subscribe_by_polling(poll_interval=1)  # poll every second

Note

According to the SiLA specification, property subscriptions are provided to “observe any change of value”. Thus, a polling subscription only emits a value if the value changed. GreetingProvider.StartYear is constant, so only one value will ever be received.

Commands

Commands are represented either by the ClientUnobservableCommand or ClientObservableCommand class. Both can be called using the command parameters as positional or keyword arguments.

Unobservable commands return the received command responses as NamedTuple instances with the class name CommandIdentifier_Responses and one field per response.

>>> client.SiLAService.SetServerName("ExampleServer")  # positional argument
SetServerName_Responses()  # no command responses

>>> client.GreetingProvider.SayHello(Name="World")  # keyword argument
SayHello_Responses(Greeting='Hello SiLA 2 World')  # one response

Observable commands return a ClientObservableCommandInstance object immediately, providing access to the command execution information:

>>> instance = client.TimerProvider.Countdown(10, Message="Countdown ended after 10 seconds")
>>> instance.done
False
>>> instance.status
<CommandExecutionStatus.running: 1>
>>> instance.progress  # in percent
20.0
>>> instance.estimated_remaining_time
datetime.timedelta(seconds=7, microseconds=332390)

Once the observable command finished (instance.status is finishedSuccessfully or finishedWithError), the method get_responses() returns the responses (if finishedSuccessfully), or raises the error (if finishedWithError).

>>> instance = client.TimerProvider.Countdown(10, Message="Countdown ended after 10 seconds")
>>> # wait 10 seconds
>>> instance.done
True
>>> instance.get_responses()
Countdown_Responses(Message='Countdown ended after 10 seconds', Timestamp=datetime.datetime(2022, 3, 8, 11, 16, 2, tzinfo=datetime.timezone.utc))

Observable commands with intermediate responses return an instance of ClientObservableCommandInstanceWithIntermediateResponses. Additional to the methods inherited from ClientObservableCommandInstance, it defines the methods get_intermediate_response() and subscribe_to_intermediate_responses(), which behave similarly to the get() and subscribe() methods of ClientObservableProperties.

>>> instance = client.TimerProvider.Countdown(10, Message="Countdown ended after 10 seconds")

>>> instance.get_intermediate_response()
Countdown_IntermediateResponses(CurrentNumber=6)

>>> subscription = instance.subscribe_to_intermediate_responses()

Note

The ClientObservableCommandInstance object internally manages a subscription to execution information. This is required for automatically updating the status, progress, estimated remaining time, and lifetime of the command instance. Use the method cancel_execution_info_subscription() to cancel this subscription.

Metadata

Metadata is represented by the ClientMetadata class. The method get_affected_calls() returns a list with the FullyQualifiedIdentifiers of all affected features, commands and properties.

>>> client.DelayProvider.Delay.get_affected_calls()
[FullyQualifiedIdentifier('de.unigoettingen/tests/DelayProvider/v1/Property/RandomNumber')]

To send metadata along with a command execution or property access request, use the optional metadata keyword argument of these methods. It is expected to be an iterable object (e.g. a list) of ClientMetadataInstances. These can be created by calling the ClientMetadata with the value to be used as metadata:

>>> client.DelayProvider.RandomNumber.get(metadata=[client.DelayProvider.Delay(1000)])
7  # result was delayed by 1 second (1000 ms)

Errors

A SiLA Server can issue these types of errors:

All exceptions not sent by the SiLA Server (usually caused by network issues) are wrapped in a SilaConnectionError.

>>> client.SiLAService.ImplementedFeatures.get(metadata=[client.DelayProvider.Delay(10)])
Traceback (most recent call last):
NoMetadataAllowed: Cannot use metadata with calls to the SiLAService feature

>>> client.TimerProvider.Countdown(-5, Message="Countdown ended")
Traceback (most recent call last):
ValidationError: Constraint validation failed for parameter de.unigoettingen/tests/TimerProvider/v1/Command/Countdown/Parameter/N: MinimalInclusive(0.0): -5

>>> client.SiLAService.GetFeatureDefinition("org.silastandard/core/UndefinedFeature/v1")
Traceback (most recent call last):
UnimplementedFeature: Feature org.silastandard/core/UndefinedFeature/v1 is not implemented by this server