Closed drvic10k closed 2 years ago
Which Beckhoff.TwinCAT.Ads Version you are using? Is it the latest? This Exception should be catched internally.
I updated to the latest 6.0.164 and it behaves the same
I am using TwinCAT.Ads.Reactive.AdsClientExtensions.WhenNotification
I checked your Reactive sample, where you use client.WhenValueChangedAnnotated
and this is not throwing the exception
Could you post here the Callstack of WhenNotification And/Or the exact overload you are using?
I am using this overload: public static IObservable<SymbolValueNotification> WhenNotification( this IAdsConnection client, ISymbol symbol, NotificationSettings settings)
with NotificationSettings.Default
call stack:
This exception was originally thrown at this call stack: TwinCAT.Ads.AdsClient.AdsSymbolVersionChanged.add(System.EventHandler<TwinCAT.Ads.AdsSymbolVersionChangedEventArgs>) System.Reactive.Linq.ObservableImpl.ClassicEventProducer<TDelegate, TArgs>.AddHandler(TDelegate) in FromEvent.cs System.Reactive.Linq.ObservableImpl.EventProducer<TDelegate, TArgs>.Session.AddHandler(TDelegate) in FromEvent.cs System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Reactive.AnonymousSafeObserver<T>.OnError(System.Exception) in AnonymousSafeObserver.cs System.Reactive.Sink<TSource, TTarget>.OnError(System.Exception) in Sink.cs System.Reactive.Subjects.Subject<T>.OnError(System.Exception) in Subject.cs System.Reactive.Linq.ObservableImpl.EventProducer<TDelegate, TArgs>.Session.AddHandler(TDelegate) in FromEvent.cs System.Reactive.Concurrency.Scheduler.ScheduleAction.AnonymousMethod__75_0(System.Reactive.Concurrency.IScheduler, (System.Action<TState> action, TState state)) in Scheduler.Simple.cs System.Reactive.Concurrency.ScheduledItem<TAbsolute, TValue>.InvokeCore() in ScheduledItem.cs ... [Call Stack Truncated]
so after some more investigation, it looks like WhenValueChangedAnnotated
is really working, I will have to check how it behaves with the real TwinCat
interesting finding though, when I use SymbolIterator
to get the symbol for the parameter of WhenValueChangedAnnotated
, I get the notifications, when I use Connection.TryReadSymbol
, the notifications don't trigger
You wont get ADS Notification when you call TryReadSymbol. Notifications are sent when you are changing values (with write). Please try the Version 6.0.178 of the Beckhoff.TwinCAT.Ads packages. I have done several improvements for the AdsSymbolicServer scenario for ArrayTypes, ElementTypes and Notifications. Furthermore, the AdsSymbolicServerSample here on GitHub is extended now to demonstrate Notification subscriptions in many variations (commit 936fa6265fbf66f8545bb53f00f42c926303cc1d)
The problem of the Exception stack above is fixed also (SymbolVersionChanged issue).
You wont get ADS Notification when you call TryReadSymbol. Notifications are sent when you are changing values (with write). Please try the Version 6.0.178 of the Beckhoff.TwinCAT.Ads packages. I have done several improvements for the AdsSymbolicServer scenario for ArrayTypes, ElementTypes and Notifications. Furthermore, the AdsSymbolicServerSample here on GitHub is extended now to demonstrate Notification subscriptions in many variations (commit 936fa62)
I meant this:
public override IObservable<T> GetObservable<T>(string symbolPath, NotificationSettings settings)
{
var symbolLoader = SymbolLoaderFactory.Create(this.Connection, SymbolLoaderSettings.DefaultDynamic);
SymbolIterator recursiveIterator = new SymbolIterator(symbolLoader.Symbols, true);
var symbol = recursiveIterator.Where(x => x.InstancePath == symbolPath);
return this.Connection
.WhenValueChangedAnnotated(symbol)
.Select(x => (T)x.Value);
}
whan I use TryReadSymbol
to get the symbol to pass to WhenValueChangedAnnotated
I get no notification, I need to use it like this
also I tried it with the new version, the problem with WhenNotification
stays, but I cannot find out the stack trace, because it's coming async from the observable
so after testing with the real TwinCat system I found out, that the workaround that works with the AdsSymbolServer does not work here
@RalfHeitmann can you please reopen this issue? it is not resolved, the same approach is not working for both real twincat and the AdsSymbolServer
Still not able to reproduce the issue, what I tried: Changed Program.Main in the SymbolicServerSample to this:
// ...
Console.WriteLine($"Symbolic Test Server runnning on Address: '{server.ServerAddress}' ...\n");
Console.WriteLine($"For testing the server see the ReadMe.md file in project root");
Console.WriteLine($"or type the following command from Powrshell with installed 'TcXaeMgmt' module:\n");
Console.WriteLine($"PS> test-adsroute -NetId {server.ServerAddress.NetId} -port {server.ServerAddress.Port}\n\n");
Console.WriteLine("Press the ENTER key to cancel...\n");
// Beneath the external access from an out-of-process ADS client
// We could also access the server from within this process
// What is done in the following for demonstration and testing purposes
// Instantiate ADS Session / Client
// and execute some operations against the SymbolicServer
SessionSettings settings = new SessionSettings(120000);
List<IDisposable> disposables = new List<IDisposable>();
using (AdsSession session = new AdsSession(AmsNetId.Local, server.ServerPort, settings))
{
// Connect to SymbolicServer
session.Connect();
IAdsConnection connection = (IAdsConnection)session.Connection;
ISymbolLoader factory = SymbolLoaderFactory.Create(session.Connection, SymbolLoaderSettings.Default);
// Load DataTypes in Symbol Instances
var types = factory.DataTypes;
var symbols = factory.Symbols;
int count1 = 0;
int count2 = 0;
IDisposable observer1 = GetObservable1<bool>(connection, symbols, "Globals.bool1", NotificationSettings.Default).Take(10).Subscribe(v => Console.WriteLine($"Observer1: Count:{++count1} Value: {v}"));
IDisposable observer2 = GetObservable2<bool>(connection, "Globals.bool1", NotificationSettings.Default).Take(10).Subscribe(v => Console.WriteLine($"Observer2: Count:{++count2} Value: {v}"));
// Wait for stopping Server Task or cancellation
await Task.WhenAny(new[] { cancelTask, serverTask });
errorCode = await serverTask;
}
// ...
public static IObservable<T> GetObservable1<T>(IAdsConnection connection, IEnumerable<ISymbol> symbols, string symbolPath, NotificationSettings settings)
{
SymbolIterator recursiveIterator = new SymbolIterator(symbols, true);
var symbol = recursiveIterator.Where(x => x.InstancePath == symbolPath);
return connection
.WhenValueChangedAnnotated(symbol)
.Select(x => (T)x.Value);
}
public static IObservable<T> GetObservable2<T>(IAdsConnection connection, string symbolPath, NotificationSettings settings)
{
IAdsSymbol symbol2 = null;
connection.TryReadSymbol(symbolPath, out symbol2);
return connection
.WhenNotification(symbol2,NotificationSettings.Default)
.Select(x => (T)(x.Value));
}
Output:
Observer1: Count:1 Value: True
Observer1: Count:2 Value: True
Observer2: Count:1 Value: True
Observer1: Count:3 Value: False
Observer1: Count:4 Value: False
Observer2: Count:2 Value: False
Observer1: Count:5 Value: True
Observer1: Count:6 Value: True
Observer2: Count:3 Value: True
Observer1: Count:7 Value: False
Observer2: Count:4 Value: False
Observer1: Count:8 Value: True
Observer1: Count:9 Value: True
Observer2: Count:5 Value: True
Observer1: Count:10 Value: False
Observer2: Count:6 Value: False
Observer2: Count:7 Value: True
Observer2: Count:8 Value: False
Observer2: Count:9 Value: True
Observer2: Count:10 Value: False
Both observers work equally well on the boolean value that is toggled per timer in the sample
I'm getting confused about the issue here ... There are also some things mixed up here ... Please try to create a little demonstration sample (best from SymbolicServerSample as starting point)
I tried with unmodified AdsSymbolicServerSample and I was surprised that AmsNetId.Local
is not localhost but it's the address of the system configured in my router
so I tried to specify localhost explicitly but the result was the same
therefore I suspect there is either some problem with my setup or somewhere internally the AmsNetId is overriden again by the router
the exception is raised in this code:
private static void CallReadValueByInstancePath(AdsSession session)
{
bool bValue = (bool) session.Connection.ReadValue("Main.bool1", typeof(bool));
string sValue = (string) session.Connection.ReadValue("Main.string1", typeof(string));
}
on the first ReadValue
I tried it with disabled twincat services running only the AdsRouter from nuget and it behaves the same I get the exception on ReadValue
I tried with unmodified AdsSymbolicServerSample and I was surprised that
AmsNetId.Local
is not localhost but it's the address of the system configured in my router
By default, AmsNetId.Local gets the AmsNetId from the router (1 ADS roundtrip) and should't show 'localhost'. So thats as-designed.
the exception is raised in this code:
private static void CallReadValueByInstancePath(AdsSession session) { bool bValue = (bool) session.Connection.ReadValue("Main.bool1", typeof(bool)); string sValue = (string) session.Connection.ReadValue("Main.string1", typeof(string)); }
on the first
ReadValue
Is this still this Exception (thought we talk about different issues now)
'Couldn't register for SymbolVersion change ...
I thought you get that error out of an 'WhenNotification' Call. The exception was mistakenly leaked by that one and that was one of the latest fixes.
The actual behaviour is, if you register for SymbolVersionChanged (which is in fact only supported by the PLC) you can get that Exception on AdsServers that doesn't support it (like the SymbolicServer).
So please (double) check, that you are not Registering SymbolVersionChanged in your code to the SymbolicServer and be sure to use the latest (fixed) version of the Beckhoff.TwinCAT.Ads and Beckhoff.TwinCAT.Ads.Reactive package also from your client side (check the loaded TwinCAT.Ads.dll and TwinCAT.Ads.Reactive.dll in debugger, often old versions of Assemblies are hanging around in bin/obj folders). If you really reproduce the Exception in the unchanged sample, this could be the only cause).
you are right, there were references to older versions of Ads and Ads.Reactive (6.0.129) held through another librtary I was using
the exception is now not thrown anymore and the notifications work
thank you very much for your patience
when trying to subscribe to the value changed notifications, I receive this error:
TwinCAT.Ads.AdsErrorException: 'Couldn't register for SymbolVersion change Notifications on the connected ADS Server. Don't register for AdsClient.SymbolVersionChanged events! (Service is not supported by server. (AdsErrorCode: 1793, 0x701))'
my subscriptions work fine with the real TwinCat server