-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathPlcConnection.cs
More file actions
128 lines (110 loc) · 4.06 KB
/
Copy pathPlcConnection.cs
File metadata and controls
128 lines (110 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using TwinCAT.Ads;
namespace PlcInterface.Ads;
/// <summary>
/// Implementation of <see cref="IPlcConnection{T}"/> for the <see cref="IAdsConnection"/>.
/// </summary>
public class PlcConnection : IAdsPlcConnection, IDisposable
{
private readonly IAdsDisposableConnection adsDisposableConnection;
private readonly BehaviorSubject<IConnected<IAdsDisposableConnection>> connectionState = new(Connected.No<IAdsDisposableConnection>());
private readonly AdsPlcConnectionOptions options;
private bool disposedValue;
/// <summary>
/// Initializes a new instance of the <see cref="PlcConnection"/> class.
/// </summary>
/// <param name="options">A <see cref="IOptions{TOptions}"/> implementation.</param>
/// <param name="logger">A <see cref="ILogger"/> implementation.</param>
/// <param name="adsDisposableConnection">The ads client used for connecting.</param>
public PlcConnection(IOptions<AdsPlcConnectionOptions> options, ILogger<PlcConnection> logger, IAdsDisposableConnection adsDisposableConnection)
{
this.options = options.Value;
this.adsDisposableConnection = adsDisposableConnection;
if (this.options.AutoConnect)
{
_ = ConnectAsync().LogExceptionsAsync(logger);
}
}
/// <inheritdoc/>
public bool IsConnected
=> adsDisposableConnection.IsConnected;
/// <inheritdoc/>
public IObservable<IConnected<IAdsConnection>> SessionStream
=> connectionState.AsObservable();
/// <inheritdoc/>
IObservable<IConnected> IPlcConnection.SessionStream
=> SessionStream;
/// <inheritdoc/>
public object Settings
=> options;
/// <inheritdoc/>
public bool Connect()
{
if (IsConnected)
{
return true;
}
var address = new AmsAddress(options.AmsNetId, options.Port);
adsDisposableConnection.ConnectionStateChanged += AdsDisposableConnection_ConnectionStateChanged;
adsDisposableConnection.Connect(address);
return adsDisposableConnection.IsConnected;
}
/// <inheritdoc/>
public Task<bool> ConnectAsync()
=> Task.Run(Connect);
/// <inheritdoc/>
public void Disconnect()
=> DisconnectAsync().GetAwaiter().GetResult();
/// <inheritdoc/>
public async Task DisconnectAsync()
{
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
_ = await adsDisposableConnection.DisconnectAsync(timeoutCts.Token).ConfigureAwait(false);
adsDisposableConnection.ConnectionStateChanged -= AdsDisposableConnection_ConnectionStateChanged;
}
/// <inheritdoc/>
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Protected implementation of Dispose pattern.
/// </summary>
/// <param name="disposing">Value indicating if we need to cleanup managed resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
Disconnect();
connectionState.OnCompleted();
connectionState.Dispose();
}
disposedValue = true;
}
}
private void AdsDisposableConnection_ConnectionStateChanged(object? sender, TwinCAT.ConnectionStateChangedEventArgs e)
{
if (sender is not IAdsDisposableConnection disposableConnection)
{
return;
}
switch (e.NewState)
{
case TwinCAT.ConnectionState.Connected:
connectionState.OnNext(Connected.Yes(disposableConnection));
break;
case TwinCAT.ConnectionState.None:
case TwinCAT.ConnectionState.Disconnected:
case TwinCAT.ConnectionState.Lost:
default:
connectionState.OnNext(Connected.No<IAdsDisposableConnection>());
break;
}
}
}