mycroes / Sally7

C# implementation of Siemens S7 connections with a focus on performance
MIT License
57 stars 23 forks source link

Reading datatype string #28

Open CommissarClippy opened 1 year ago

CommissarClippy commented 1 year ago

I can read the datatype string with the following line: DataBlockDataItem<byte[]> dataItemString = new DataBlockDataItem<byte[]> { DbNumber = 2, StartByte = 40, Length = 200 }; And converting it to a string with the next line: Encoding.Default.GetString(dataItemString.Value)

Although I must say I expected to be able to read it like this: DataBlockDataItem<string> dataItemStringString = new DataBlockDataItem<string> { DbNumber = 2, StartByte = 40 }; Which throws the following exception: System.AggregateException HResult=0x80131500 Message=One or more errors occurred. (Read of dataItem Sally7.DataBlockDataItem1[System.String] returned DataTypeNotSupported) Source=Sally7 StackTrace: at Sally7.S7ConnectionHelpers.ParseReadResponse(ReadOnlySpan1 buffer, ReadOnlySpan1 dataItems) at Sally7.S7Connection.<ReadAsync>d__31.MoveNext() at Sandbox.Program.<Read>d__1.MoveNext() in D:\Projects\Sandbox\Sandbox\Program.cs:line 43

Inner Exception 1: Exception: Read of dataItem Sally7.DataBlockDataItem1[System.String] returned DataTypeNotSupported

This aside, reading the bytes and converting this to a string works.

My real problem starts when trying to read the string: dataItemString.Value = Encoding.Default.GetBytes("Test"); Which writes the converted bytes to the DB: X#(54 65 73 74 72 64 69 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00) I can read them again using the working read method for the string, but I want the string to be decoded in the DB.

Writing through the string datatype for the DataBlockDataItem results in an empty string in the DB (''). DataBlockDataItem<string> dataItemStringString = new DataBlockDataItem<string> { DbNumber = 2, StartByte = 40 }; dataItemStringString.Value = "Test";

How can I write the datatype string?

mycroes commented 1 year ago

You need to specify the length as well: new DataBlockDataItem<string> { DbNumber = 2, StartByte = 40, Length = 200 }.

Not setting Length means it's 0, unless typeof(T).IsValueType == true, it'll then be set to 1 (because you can't read multiple of int / float / whatever into a single variable).

Also, the string support has some magic:

  1. Strings in S7 have a header consisting of the reserved length and the allocated length, Sally7 will add 2 to the Length specified to cater for this header.
  2. When writing the reserved length is set to Length and the allocated length is set to the string length (or 0 when the value is null)

So please ensure Length is set to the string length defined in the PLC and that the StartByte points to the address of the header (which I believe is exactly the address shown in TIA Portal as well).

Last but not least, the exception you're getting is upon parsing the response from the PLC, so apparently there's something triggering an error PLC-side while I think the request would be perfectly valid (but only reading the string header), that's something I'll have to look into.

I'll also see if I can add some sanity checks to avoid Length not being set, perhaps changing the mutability of the DataBlockDataItem to permit checking at construction time.

mycroes commented 1 year ago

Some of this has been addressed in 935168bc9b7b7e18c17a6d4910981eb0e0071b45. There's no released version with that change yet, but then again this only adds some additional sanity checks on length passed to DataBlockDataItem.