class documentation

class RemoteLock(RemoteUaObject['BaseRemoteComponent'], UaDataChangeSubscriber):

Constructor: RemoteLock(parent, server, ua_node, max_inactive_lock_time, ...)

View In Hierarchy

The remote interface for a server-side Lock.

State model

The state properties (locked, locked_since, locking_user, locking_client, locked_by_us, remaining_lock_time_ms) are a local cache fed by an OPC UA data-change subscription. They are only eventually consistent with the server:

  • They can lag by up to one publishing interval, including right after init_lock, break_lock, exit_lock or renew_lock returns.
  • Nodes are notified separately, so values may briefly disagree with each other.
  • A notification queued before a read_state call can arrive after it and briefly revert a field.
  • remaining_lock_time_ms is the last reported value and is not counted down locally.

Intended use

Use the cache for displaying status and reacting to changes made by others. A successful init_lock or break_lock means we hold the lock; there is no need to wait for locked_by_us. The server enforces lock ownership, so a stale cache can at worst cause a rejected call, never an unauthorized one.

Use read_state when the exact state is needed. It reads all nodes in one request, returns an immutable consistent snapshot and by default updates the cache.

Signals

locked_changed and locking_user_changed fire only when the cached value changes, from any source, and can occasionally flicker. renew_due fires while we hold the lock and the remaining time is below renew_threshold (a fraction of the maximum), at most every renew_retry_seconds. A spurious renew_due is harmless.

Method __init__ Create a new instance. Must be asynchronously initialized with init() before use.
Async Method break_lock Take over the lock from its current holder.
Async Method exit_lock Release the lock.
Async Method init_lock Acquire the lock.
Method max_inactive_lock_time_ms.setter Undocumented
Async Method read_state Read the current lock state from the server in a single request.
Async Method renew_lock Reset the lock's inactivity timer.
Method renew_retry_seconds.setter Undocumented
Method renew_threshold.setter Undocumented
Async Method ua_on_data_change Undocumented
Instance Variable locked_changed Callback when the locked status changed. Payload is locked status.
Instance Variable locking_user_changed Callback when a lock user changed. Payload is the new user name.
Instance Variable max_inactive_lock_time_ms Maximum inactive lock time in ms.
Instance Variable renew_due Callback when a lock renew is due. Payload contains the remaining lock time in milliseconds.
Property locked Whether the corresponding machine/component is locked. Cached, see the class docstring.
Property locked_by_us Whether locked and locking_user equals the server username. Derived from cached values.
Property locked_since When the lock was acquired, None when unlocked. Cached, see the class docstring.
Property locking_client Hostname of the locking client, empty when unlocked. Cached, see the class docstring.
Property locking_user Name of the locking user, empty when unlocked. Cached, see the class docstring.
Property remaining_lock_time_ms Remaining lock time in ms as last reported by the server, None when unlocked.
Property renew_retry_seconds Minimum seconds between two renew_due events while still below the threshold (> 0).
Property renew_threshold Fraction of MaxInactiveLockTime below which a renewal is requested (0 < x < 1).
Property ua_nodes Return all raw OPC UA nodes related to this RemoteLock.
Async Method _apply_state Undocumented
Async Method _browse Undocumented
Async Method _check_renew_due Undocumented
Async Method _init Undocumented
Async Method _ua_read_max_inactive_lock_time Undocumented
Instance Variable _last_renew_request Undocumented
Instance Variable _locked Undocumented
Instance Variable _locked_since Undocumented
Instance Variable _locking_client Undocumented
Instance Variable _locking_user Undocumented
Instance Variable _max_inactive_lock_time_ms Undocumented
Instance Variable _remaining_lock_time_ms Undocumented
Instance Variable _renew_retry_seconds Undocumented
Instance Variable _renew_threshold Undocumented
Instance Variable _ua_nodes Undocumented
def __init__(self, *, parent: BaseRemoteComponent, server: RemoteServer, ua_node: Node | None = None, max_inactive_lock_time: int = 60000, renew_threshold: float = 0.5, renew_retry_seconds: float = 1.0):

Create a new instance. Must be asynchronously initialized with init() before use.

Parameters
parent:BaseRemoteComponentUndocumented
server:RemoteServerUndocumented
ua_node:Node | NoneUndocumented
max_inactive_lock_time:intDefault MaxInactiveLockTime in milliseconds. Will be overridden if the server provides this information.
renew_threshold:floatFraction of MaxInactiveLockTime below which a renewal is requested (0 < x < 1).
renew_retry_seconds:floatMinimum seconds between two renew_due events while still below the threshold (> 0).
async def break_lock(self):

Take over the lock from its current holder.

On success, we hold the lock; there is no need to wait for locked_by_us. The cache is updated by the subscription and may show the previous owner for up to one publishing interval.

Raises
UaErrorIf the server rejects the call, e.g. the holder has higher priority or the user is not permitted to break locks.
async def exit_lock(self):

Release the lock.

On success, the lock is released, even if locked and locked_by_us still read True until the subscription catches up.

Raises
UaErrorIf the server rejects the call, e.g. we are not the locking user.
async def init_lock(self):

Acquire the lock.

On success, we hold the lock; there is no need to wait for locked_by_us. The cache is updated by the subscription and may show the old state for up to one publishing interval.

Raises
UaErrorIf the server rejects the call, e.g. the lock is already held or the user is not permitted.
def max_inactive_lock_time_ms(self, value: int):

Undocumented

async def read_state(self, *, update_cache: bool = True) -> RemoteLockState:

Read the current lock state from the server in a single request.

Bypasses the cache and returns a consistent snapshot.

Parameters
update_cache:boolAlso apply the snapshot to the cache, emitting signals for changes.
Returns
RemoteLockStateUndocumented
Raises
OpenSmiRuntimeErrorIf a node could not be read or returned no value.
async def renew_lock(self):

Reset the lock's inactivity timer.

On success, we still hold the lock and the timer is reset. remaining_lock_time_ms stays low until the next notification, so another renew_due may fire meanwhile (throttled); renewing again is harmless.

Raises
UaErrorIf the server rejects the call, e.g. we are not the locking user.
def renew_retry_seconds(self, value: float):

Undocumented

def renew_threshold(self, value: float):

Undocumented

@override
async def ua_on_data_change(self, node: Node, val: Any, data: DataChangeNotif):

Undocumented

locked_changed =

Callback when the locked status changed. Payload is locked status.

locking_user_changed =

Callback when a lock user changed. Payload is the new user name.

@property
max_inactive_lock_time_ms: int =

Maximum inactive lock time in ms.

Read once from the server during initialization (assumed constant), otherwise the default from __init__. Raised automatically if the server reports a larger remaining time.

renew_due =

Callback when a lock renew is due. Payload contains the remaining lock time in milliseconds.

@property
locked: bool =

Whether the corresponding machine/component is locked. Cached, see the class docstring.

@property
locked_by_us: bool =

Whether locked and locking_user equals the server username. Derived from cached values.

Can lag behind the server, e.g. right after init_lock. Use read_state for an exact answer.

@property
locked_since: datetime | None =

When the lock was acquired, None when unlocked. Cached, see the class docstring.

Taken from the server timestamp of the notification or read; falls back to local time if the server provides none, so treat it as approximate.

@property
locking_client: str =

Hostname of the locking client, empty when unlocked. Cached, see the class docstring.

@property
locking_user: str =

Name of the locking user, empty when unlocked. Cached, see the class docstring.

@property
remaining_lock_time_ms: int | None =

Remaining lock time in ms as last reported by the server, None when unlocked.

Cached and not counted down locally. Renewal is normally driven by renew_due, not by polling this.

@property
renew_retry_seconds: float =

Minimum seconds between two renew_due events while still below the threshold (> 0).

@property
renew_threshold: float =

Fraction of MaxInactiveLockTime below which a renewal is requested (0 < x < 1).

@property
ua_nodes: RemoteLockUaNodes =

Return all raw OPC UA nodes related to this RemoteLock.

async def _apply_state(self, *, locked: bool | None = None, locked_since: datetime | None = None, locking_user: str | None = None, locking_client: str | None = None, remaining_ms: int | None = None):

Undocumented

async def _browse(self):

Undocumented

async def _check_renew_due(self):

Undocumented

@override
async def _init(self):

Undocumented

async def _ua_read_max_inactive_lock_time(self):

Undocumented

_last_renew_request: float | None =

Undocumented

_locked =

Undocumented

_locked_since: datetime | None =

Undocumented

_locking_client =

Undocumented

_locking_user =

Undocumented

_max_inactive_lock_time_ms: int =

Undocumented

_remaining_lock_time_ms: int | None =

Undocumented

_renew_retry_seconds: float =

Undocumented

_renew_threshold: float =

Undocumented

_ua_nodes: RemoteLockUaNodes =

Undocumented