Table of Contents

Class ConnectedDevice

Namespace
Acuit.Pinpoint.IO
Assembly
Acuit.Pinpoint.IO.Abstractions.dll

A base class for implementing IConnectedDevice and IHealthCheck.

public abstract class ConnectedDevice : IConnectedDevice, IHealthCheck, IDisposable, IAsyncDisposable
Inheritance
ConnectedDevice
Implements
Derived
Inherited Members

Remarks

Derived classes must do the following:

See the remarks for the referenced members for more details.

Constructors

ConnectedDevice(ILogger)

Initializes a new instance of the ConnectedDevice class.

[CLSCompliant(false)]
protected ConnectedDevice(ILogger logger)

Parameters

logger ILogger

The logger.

Exceptions

ArgumentNullException

logger is null.

Methods

CheckHealthAsync(HealthCheckRegistration, CancellationToken)

Runs the health check, returning the status of the component being checked.

public Task<HealthCheckResult> CheckHealthAsync(HealthCheckRegistration registration, CancellationToken cancellationToken = default)

Parameters

registration HealthCheckRegistration

The health check registration associated with the current execution.

cancellationToken CancellationToken

A CancellationToken that can be used to cancel the health check.

Returns

Task<HealthCheckResult>

A Task<TResult> that completes when the health check has finished, yielding the status of the component being checked.

ConnectAsync(CancellationToken)

Connects to the device.

public Task<IDeviceConnection> ConnectAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A CancellationToken that can request canceling the connection attempt.

Returns

Task<IDeviceConnection>

A task that represents the asynchronous operation. The value of its Result property contains a IDeviceConnection representing the established connection.

Remarks

This is safe to call even if there is already an active connection, in which case it will do nothing and return the same IDeviceConnection as from the active connection.

Implementations must ensure that the returned IDeviceConnection is fully implemented, including handling callback registrations and indicating when the connection is closed for any reason.

Upon a successful connection, Connected should be raised.

This must be thread-safe: asynchronous implementations must ensure multiple simultaneous calls to this are handled correctly.

Exceptions

Exception

The connection could not be established. Specific exception types will depend on the implementation.

ConnectedCheckHealthAsync(CancellationToken)

Perform a health check on a connected device.

protected virtual Task<HealthCheckResult> ConnectedCheckHealthAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

A CancellationToken that can be used to cancel the health check.

Returns

Task<HealthCheckResult>

A Task<TResult> that completes when the health check has finished, yielding the status of the component being checked.

Remarks

ConnectedDevice implements IHealthCheck by default to simply confirm that a connection exists (or can be made) to the device; it basically reflects the status of the DoConnectAsync(CancellationToken) implementation's latest result. If that is sufficient for a device implementation, then this method should not be overridden and ConnectedHealthIsHealthy() need never be called.

This method should be overridden if there are additional actions needed to verify device health, beyond DoConnectAsync(CancellationToken) connectivity. For example:

  • A device implementation might "connect" to a device by simply opening a serial port for communication. Therefore, the default health check only represents the status of the local serial port. In this case, it would probably be appropriate to override this method to perform some kind of communication with the device to confirm that the device is there and is responsive.
  • A device might need to be in a certain state to operate properly, such as a PLC that needs to be in "Run" mode. In this case, this method could be overridden to read the status from the device and confirm it is in the correct state.

Override implementations:

  • Must not call ConnectedDeviceLockAsync(CancellationToken), as a lock will already exist when this gets called.
  • Can simply throw a synchronous exception or complete the returned task with a fault exception to indicate an unhealthy status, which will cause an unhealthy "Connection problem" result to be reported.
  • Can return a HealthCheckResult result indicating a specific health status and a specific description.
  • Should not call ConnectedHealthIsHealthy() to indicate a healthy status, but rather return a Healthy result.
  • Need not call the base implementation, as it simply returns a Healthy result.

Exceptions

Exception

The device is unhealthy.Specific exception types will depend on any override(s).

ConnectedDeviceLockAsync(CancellationToken)

Ensures the device is connected and acquires a lock on the device connection.

protected Task<IDisposable> ConnectedDeviceLockAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

A CancellationToken that can request canceling waiting for the lock and connecting to the device.

Returns

Task<IDisposable>

A task that represents the asynchronous operation. The value of its Result property contains a disposable that releases the lock when disposed.

Exceptions

Exception

The connection could not be established. Specific exception types will depend on the implementation of DoConnectAsync(CancellationToken), any OnConnectedAsync() override(s), and any Connected event handlers.

ConnectedHealthIsHealthy()

Derived classes can call this at any time to indicate that the health of the connection with the device was confirmed to be healthy.

protected void ConnectedHealthIsHealthy()

Remarks

When this has been called at least once since the last health check, then the call to ConnectedCheckHealthAsync(CancellationToken) during the next health check will be skipped. This is typically called from public methods that work with the connected device once they succeed, when the event is enough to verify device health.

This need only be called when ConnectedCheckHealthAsync(CancellationToken) is overridden with custom health check logic, as this is only used to determine when the call to ConnectedCheckHealthAsync(CancellationToken) can be skipped. Typically this is used when ConnectedCheckHealthAsync(CancellationToken) is simply used to confirm that the device is there and responds to communication, and thus can be skipped when other successful communication with the device is occurring. This should typically not be used when ConnectedCheckHealthAsync(CancellationToken) performs a check that is not performed by other public methods (e.g., checking that a PLC is in "Run" mode).

DisconnectAsync(CancellationToken)

Disconnects from the device.

public Task DisconnectAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A CancellationToken that can request that the disconnection process no longer be graceful.

Returns

Task

A task that represents the asynchronous operation.

Remarks

This is safe to call even if there is not an active connection.

When cancellationToken is signaled, it indicates that the disconnection should still occur, but not gracefully. The implementation should complete its disconnection process as directly as possible, but the returned Task should still reflect a RanToCompletion status (not Canceled).

Upon a successful connection, Disconnected should be raised.

This must be thread-safe: asynchronous implementations must ensure multiple simultaneous calls to this are handled correctly.

Dispose()

Closes and releases all resources used by the object.

public void Dispose()

Dispose(bool)

Closes and releases all resources used by the object.

protected virtual void Dispose(bool disposing)

Parameters

disposing bool

true when this is in response to a call to Dispose().

Remarks

Derived classes should override this when they have any resources that should be disposed.

When Dispose() is called on the object, Dispose(bool) will be called with true for the parameter value.

When DisposeAsync() is called on the object, DisposeAsyncCore() will be called, and then Dispose(bool) will be called with false for the parameter value.

DisposeAsync()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously.

public ValueTask DisposeAsync()

Returns

ValueTask

A task that represents the asynchronous operation.

DisposeAsyncCore()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously.

protected virtual ValueTask DisposeAsyncCore()

Returns

ValueTask

A task that represents the asynchronous operation.

Remarks

Derived classes should override this when they have any resources that should be disposed.

When Dispose() is called on the object, Dispose(bool) will be called with true for the parameter value.

When DisposeAsync() is called on the object, DisposeAsyncCore() will be called, and then Dispose(bool) will be called with false for the parameter value.

DoConnectAsync(CancellationToken)

Connects to the device.

protected abstract Task DoConnectAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

A CancellationToken that can request canceling the connection attempt.

Returns

Task

A task that represents the asynchronous operation.

Remarks

This might be called from any thread, but it and DoDisconnectAsync(CancellationToken) will never be called concurrently.

Exceptions

Exception

The connection could not be established. Specific exception types will depend on the implementation.

DoDisconnectAsync(CancellationToken)

Disconnects from the device.

protected abstract Task DoDisconnectAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

A CancellationToken that can request that the disconnection process no longer be graceful.

Returns

Task

A task that represents the asynchronous operation.

Remarks

When cancellationToken is signaled, it indicates that the disconnection should still occur, but not gracefully. The implementation should complete its disconnection process as directly as possible, but the returned Task should still reflect a RanToCompletion status (not Canceled).

This might be called from any thread, but it and DoConnectAsync(CancellationToken) will never be called concurrently.

OnConnectedAsync()

Called after DoConnectAsync(CancellationToken) completes successfully.

protected virtual Task OnConnectedAsync()

Returns

Task

A task that represents the asynchronous operation.

OnDisconnectedAsync()

Called after DoDisconnectAsync(CancellationToken) completes successfully.

protected virtual Task OnDisconnectedAsync()

Returns

Task

A task that represents the asynchronous operation.

OnDisconnectingAsync(CancellationToken)

Called before DoDisconnectAsync(CancellationToken) will be called.

protected virtual Task OnDisconnectingAsync(CancellationToken cancellationToken)

Parameters

cancellationToken CancellationToken

A CancellationToken that can request that the disconnection process no longer be graceful.

Returns

Task

A task that represents the asynchronous operation.

Remarks

When cancellationToken is signaled, it indicates that the disconnection should still occur, but not gracefully. The returned Task should reflect a RanToCompletion status (not Canceled).

OnExternalDeviceClosedConnection(Exception)

Derived classes should call this when the external device closes the connection, but being careful not to call it while disconnection is underway.

protected virtual void OnExternalDeviceClosedConnection(Exception closeError)

Parameters

closeError Exception

The exception representing the connection lost error.

Remarks

closeError is required, since CloseError should only be null when the connection is still open or when it was closed via DisconnectAsync(CancellationToken). If there was no exception that raised the lost connection, then provide a created exception. DeviceClosedConnectionException can be used for this, which will provide a message like "The device closed the connection."

Exceptions

ArgumentNullException

closeError is null.

InvalidOperationException

There is no active connection, or a connection or disconnection process is in progress.

Events

Connected

Raised when the device is connected.

public event EventHandler Connected

Event Type

EventHandler

Disconnected

Raised when the device is disconnected.

public event EventHandler Disconnected

Event Type

EventHandler