I'm trying to write C# application where ADS client will automatically reconnect/renew reading/writing values and subscriptions when application lost connection with PLC or new version of PLC program will be downloaded.
I'm using TwinCAT.Ads.Reactive v4.4.0 library from NuGet.
My program flow is:
Connect to ADS server (connection successful)=>
- Create reactive notification with ValueSymbolExtensions.WhenValueChanged
Create reactive cyclic write value ValueSymbolExtensions.WriteValues
- 3[a] Create reactive cyclic poll values AnyTypeExtensions.PollValues.T
- 3[b] I have also tried ValueSymbolExtensions.PollValues which is not documented yet on Beckhoff website
So far I have find out that 1. and 2. works even if I unplug ethernet cable or downlaod new program to PLC -> the WriteValues() and WhenValueChanged() renew itself internally
CODE:
// WhenValueChanged()
TreeViewSymbols = SymbolLoaderFactory.Create(_client, SymbolLoaderSettings.Default).Symbols; // Load symbol tree from plc
IValueSymbol boolVal = (IValueSymbol)TreeViewSymbols["SomeBoolValue"];
boolVal.WhenValueChanged().Subscribe(Observer.Create<object>(val => ArchiveData((bool)val)));
// WriteValues()
IValueSymbol toggleBit = (IValueSymbol)TreeViewSymbols["toggle_bit"];
toggleBit.WriteValues(
Observable.Interval(TimeSpan.FromSeconds(1.0)).Select(x => x % 2 == 0 ? false : (object)true),
e => Debug.WriteLine($"Error writing toggle bit")
);
I read in PollValues() every second custom struct of Data. During normal run this works fine, but after I change PLC program and download changes to PLC or connection is lost (unpluged ethernet cable) this subscription fails internally and do not recover like the ones above.
IValueSymbol state = (IValueSymbol)TreeViewSymbols[Cfg.ModuleStateTag];
state.PollValues(TimeSpan.FromSeconds(1.0))
.Subscribe(Observer.Create<object>(
val => // val comes as byte[] array
{
var a = new ModuleStateData((byte[])val);
Debug.WriteLine($"Status values Machine Mode:{a.MachineMode}");
},
e => Debug.WriteLine($"Error reading status"),
() => Debug.WriteLine($"OnComplete???? reading status"))
).AddDisposableTo(_disposables);
_client.PollValues<ModuleStateData>(
Cfg.ModuleStateTag,
TimeSpan.FromSeconds(1.0)
).Subscribe(Observer.Create<object>(
val =>
{
Debug.WriteLine($"Status values Machine Mode:{val.MachineMode});
},
e => Debug.WriteLine($"Error reading status - {e.Message}"),
() => Debug.WriteLine($"OnComplete???? reading status"))
).AddDisposableTo(_disposables);
ConnectionStateChanged
Also connection state changed event is fired only if I call Connect()/Disconnect() on ads client, and not on connection problems. Any idea how can I find out there is a connection problem?