Write failing with BadWriteNotSupported error

Questions regarding the use of the .NET SDK 2.0 for Server or Client development or integration into customer products ...

Moderator: uasdknet

Post Reply
greggw
Sr. Member
Sr. Member
Posts: 11
Joined: 08 Oct 2013, 20:46

Write failing with BadWriteNotSupported error

Post by greggw »

I am trying to write to a TOPServer instance to set a coil on a device. I am using the servers support for dynamic tags to construct a tag, knowing the NodeId of the parent "Tag". What I get back from the write is BadWriteNotSupported. I don't understand why this is happening, and am trying to figure out how to debug the problem to know where the problem actually is at. I don't see any complaints in the TOPServer log output, so I'm wondering if the problem is in the client SDK code or what?

NodeId nodeToWrite = NodeId.Parse(device.nodeId + ".0" + itm.Address );

List<WriteValue> nodesToWrite = new List<WriteValue>();

WriteValue wv = new WriteValue();
wv.Value = new DataValue(new Variant(true));
wv.NodeId = nodeToWrite;
wv.AttributeId = Attributes.Value;
wv.UserData = device;
nodesToWrite.Add(wv);
List<StatusCode> success = session.Write(nodesToWrite);

greggw
Sr. Member
Sr. Member
Posts: 11
Joined: 08 Oct 2013, 20:46

Re: Write failing with BadWriteNotSupported error

Post by greggw »

Ultimately, the code below creates a working "NodeId.Parse" operation, and for "subscription" and "read", this syntax creates a working NodeId. That is, I get updates for these tags with subscriptions, and I can "read" the tags as well.

So, does anyone have any insight into why just Write is not working with the TOP Server from software toolbox? This is a very frustrating situation, and my evaluation of unified-automation's tools isn't leaving me with a good impression. There should be much more information in the Write failure message that indicates the specifics of what needs to be fixed. Yes, the docs do say that BadWriteNotSupport will be returned if the server doesn't support writing of the server or user timestamps. I don't understand how to know that is happening given the very brief detail returned to me.

Also, I used UAExpert to perform the following test.

1) define a tag on my server named 0104.
2) rebrowse with UAExpert to reveal that tag.
3) delete that tag from the server.
4) perform a value write with that tag on UAExpert

My reasoning, is that this should emulate the use of a 'dynamic' tag (supported by TOP Server, which will then use the 'numeric' value of the tag name as a MODBUS address on the device, and will then dynamically create a tag to use for the request). It seems to, as the "write" operations appear to still work, even through the tag is gone from the server.

Any insight would be very much appreciated.

Code: Select all

NodeId nodeToWrite = NodeId.Parse(device.nodeId + ".0" + itm.Address );

List<WriteValue> nodesToWrite = new List<WriteValue>();

WriteValue wv = new WriteValue();
wv.Value = new DataValue(new Variant(true));
wv.NodeId = nodeToWrite;
wv.AttributeId = Attributes.Value;
wv.UserData = device;
nodesToWrite.Add(wv);
List<StatusCode> success = session.Write(nodesToWrite);

greggw
Sr. Member
Sr. Member
Posts: 11
Joined: 08 Oct 2013, 20:46

Re: Write failing with BadWriteNotSupported error

Post by greggw »

Okay, after beating my head against the wall, the problem is exactly that described in

http://www.opclabs.com/forum/quickopc-u ... 0x80730000

So, I added the following to my WriteValue initialization:

Code: Select all

			wv.Value.ServerTimestamp = new DateTime(0);
			wv.Value.SourceTimestamp = new DateTime(0);
One thing that is just not good object design, with the Unified-Automation classes, is that there are not convenience constructors, or those that would allow the normal object initialization to occur. This SDK is very much like the old structures of 20years ago when OO programming was not really happening much yet.

Now, we know in good OO API design, that you "never" provide an empty constructor when your object has a minimum set of "member values" which must be set. Also, you don't provide "default" initialization for something which can not be specified in a constructor as not initialized.

In this case, the DateTime class is a very broken object that demands a non-null value to imply non-initialized, so it's problematic to do this for these values as I've done above.

But, overall, the APIs in this SDK really need a lot of work to clean up constructors, and provide documentation which details what is and isn't required for "functionality" to work.

The Session.Write() method documents that writes might fail if timestamps can not be set. That implies that there should be a complete code path where a user doesn't have to "de-initialize" something to have it work. So, the WriteValue class should have a constructor with a DataValue object only which does not initialize the dates to "now", and the documentation of that constructor should say that it doesn't do that, and another constructor with the DataValue, and the two DateTime arguments which does initialize the DateTime values with the passed values.

User avatar
Support Team
Hero Member
Hero Member
Posts: 3072
Joined: 18 Mar 2011, 15:09

Re: Write failing with BadWriteNotSupported error

Post by Support Team »

The Unified Automation .NET SDK was designed assuming that people would use the following construct from the C# 3.0 language:

Code: Select all

new DataValue() {  WrappedValue = 1 }

or

Code: Select all

new DataValue() { WrappedValue = "Something",  SourceTimestamp = DataTime.UtcNow }
This design pattern eliminates the need for overloaded constructors and most classes do not offer any overloaded versions of the constructor for that reason. All of the GettingStarting examples that come with the SDK use this design pattern.

The behavior of the DataValue class is an exception and was designed originally for the Server SDK where setting the timestamps is a useful convince. However, this creates problems on the client side which you have noted.

Unfortunately, once the SDK was released with this behaviour it cannot be changed because people will have designed code expecting this behavior. That said, the missing documentation is a serious problem that will be corrected with the next version.

When you run into these kinds of problems it can be useful to look at the GettingStarted examples which provide simple examples of all major SDK features. In the case of Write, the example uses the recommended design pattern:

Code: Select all

nodesToWrite.Add(new WriteValue()
{
    NodeId = nodeId,
    AttributeId = Attributes.Value,
    Value = new DataValue() { WrappedValue = variable.Value },
    UserData = Result2TB // the UserData can be used to store application state information.
});


We appreciate your feedback and will act on it since we strive to provide the best SDKs available on the market.

Best Regards
Support Team

greggw
Sr. Member
Sr. Member
Posts: 11
Joined: 08 Oct 2013, 20:46

Re: Write failing with BadWriteNotSupported error

Post by greggw »

Code: Select all

new DataValue() {  WrappedValue = 1 }
So, does this not initialize the two timestamps? I am still confused by how an API user knows what value the timestamps are set to. Does one always have to specify them to make sure they are set to Ticks=0?

In addition, while I understand that .Net provides a simple way to have lots of properties and not so many constructors, it is still poor object design to not provide overloaded constructors which enumerate the required parameters. It might be convenient for SDK developers to not have to create overloaded constructors, but for developers, it is just completely unproductive to constantly have to go read documentation on a class to understand which properties must be set. On top of that, as already noted, the documentation for many of the UA SDK classes is just not useful. The documentation states, for most properties no information about how to use it, why you might choose to use it, or what effects it will have on the application.

The IDE has code completion and shows hints for good reason. It's what developers rely on for productivity and for learning how to use APIs by being greeted with documentation that fully explains how things work.

User avatar
Support Team
Hero Member
Hero Member
Posts: 3072
Joined: 18 Mar 2011, 15:09

Re: Write failing with BadWriteNotSupported error

Post by Support Team »

Hello Greg,

- The default constructor initializes the TimeStamps to 0.
- We are extending the documentation successively. But for now you can use the Client GettingStarted examples to get an overview of the common usage of the API methods.

Best regards
Support Team

Post Reply