Closed drvic10k closed 2 years ago
Please give more information which overload of WriteAsync you are using because there are several paramater sets. Another important information what type of instance you want to write and the addressing (PrimitiveType, ComplexType). What is the system reaction? Is the call just ignored or do you get an Exception? Is OnWriteRawValue called in this situation?
I am using this method:
public async Task<ResultWrite> WriteAsync(
uint indexGroup,
uint indexOffset,
ReadOnlyMemory<byte> writeBuffer,
CancellationToken cancel)
when writing one symbol I get this exception, it's a boolean value:
Parameter size is incorrect. (AdsErrorCode: 1797, 0x705)
but with Connection.WriteValueAsync
it works
another boolean value works with both methods
The relevant implementation part in the SymbolServer base class could be this one here:
protected virtual Task<ResultWrite> OnWriteIgIoAsync(AmsAddress sender, uint invokeId, uint indexGroup, uint indexOffset, ReadOnlyMemory<byte> writeData, CancellationToken cancel)
{
AdsErrorCode errorCode = AdsErrorCode.DeviceServiceNotSupported;
SymbolIterator iter = new SymbolIterator(this.symbols, true);
IAdsSymbol? symbol = iter.Cast<IAdsSymbol>().FirstOrDefault(s => s.IndexGroup == indexGroup && s.IndexOffset == indexOffset);
if (symbol != null)
{
if (writeData.Length == symbol.GetValueMarshalSize())
{
byte[] data = new byte[symbol.GetValueMarshalSize()];
try
{
errorCode = OnWriteRawValue(symbol, writeData.Span);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
errorCode = AdsErrorCode.InternalError;
}
}
else
{
errorCode = AdsErrorCode.DeviceInvalidSize;
}
}
return Task.FromResult(new ResultWrite(errorCode,invokeId));
}
Could it be that the IndexGroup, IndexOffset combination returns a symbol that is ambigous or doesn't return the boolean symbol you expect?
Edit: Changed the Read method to Write
I tried to override the method and set a breakpoint there, it doesn't hit it before the exception is thrown
another boolean value works with both methods
I really don't know where this issue should come from. It must have to do with the Symbol/Value: If I add the following code into the AdSymbolicServer program.cs file (behind registering all Notifications):
// Receiving notifications on all Symbols
SymbolIterator iter = new SymbolIterator(symbols,true);
IList<ISymbol> allSymbols = iter.ToList();
disposables = ReceiveNotifications(session,allSymbols);
// Add this part for WriteAsync usage
IAdsSymbol b1 = (IAdsSymbol)symbols["Main.bool1"];
IAdsSymbol b2 = (IAdsSymbol)symbols["Globals.bool1"];
byte[] bytes = new byte[1];
for (int i = 0; i < 10; i++)
{
await Task.Delay(TimeSpan.FromSeconds(1.0));
bytes[0] = (bytes[0] == (byte)1) ? (byte)0 : (byte)1;
await session.Connection.WriteAsync(b1.IndexGroup, b1.IndexOffset, bytes.AsMemory(), CancellationToken.None);
await session.Connection.WriteAsync(b2.IndexGroup, b2.IndexOffset, bytes.AsMemory(), CancellationToken.None);
}
I even get the Ads Notifications from the Value toggling properly. Also I don't see the potential for an DeviceInvalidSize return code other than described above (picking up the wrong symbol or Incorrect designed Symbol from IndexGroup/IndexOfset, or MemorySpan.Length != 1. Relevant is here the ByteSize of the Symbol (should be 1 for an boolean), and that WriteAsync gets the correct buffer size (also 1-byte).
when writing one symbol I get this exception, it's a boolean value:
Parameter size is incorrect. (AdsErrorCode: 1797, 0x705)
but withConnection.WriteValueAsync
it worksanother boolean value works with both methods
Is the problem still reproducable on your side?
yes, it is reproducible, I will try do some more investigation today to see what is the difference between those two values
so delving deeper, I found out, that the result of the operation is DeviceInvalidSize
can this be cause by the way the subsymbols are mapped?
here you can see that the struct has the same offset as the field
and I am trying to write the value like this:
Connection.WriteAsync(symbol.IndexGroup, symbol.IndexOffset, memory, cancel)
, offset is 4154, allocated memory is one byte (4154 dec = 103A hex)
when writing the next value (103B), it works fine
same problem happens when reading
I tried to follow the code execution of this method, because it can write the symbol correctly, to see the difference:
public async Task<ResultWrite> WriteValueAsync(
ISymbol symbol,
object val,
CancellationToken cancel)
there is a strange thing happening, this symbol is transformed to this:
in this method:
public async Task<ResultWrite> WriteValueAsync(
string name,
object value,
CancellationToken cancel)
and then with this different index group and offset it somehow correctly arrives in the simulator with the original group and offset
That explains the problem. There is a side effect in the AdsClient-side cached ISymbols when you use the "ReadValueXXX" and "WriteValueXXX" overloads (Changing the IndexGroup to IndexGroupSymbolAccess.ValueByHandle and the Handle as IndexOffset). This one never caused trouble with other AdsServers - but with the specific SymbolicServer implementation. I need to have a look how to change this - but that would need a little bit of work, it's not an easy one ...
Please try out the 6.0.190 ...
now it works, thanks
with the
AdsSymbolicServer
, I cannot useConnection.WriteAsync
, I had to replace the call withConnection.WriteValueAsync
is there some other method I need to override to make
WriteAsync
work? I am overridingprotected override AdsErrorCode OnWriteRawValue(ISymbol symbol, ReadOnlySpan<byte> span)