Skip to content

Commit 70d5afc

Browse files
committed
Changes required for working ExampleRaw.cs
1 parent b28ec4d commit 70d5afc

File tree

6 files changed

+88
-115
lines changed

6 files changed

+88
-115
lines changed

examples/CSharp DotNetCore/ExampleRaw.cs

Lines changed: 49 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -7,132 +7,74 @@
77

88
using System;
99
using System.Collections.Generic;
10-
using System.Linq;
1110
using System.Text;
11+
using System.Buffers.Binary;
1212
using libplctag;
1313

1414
namespace CSharp_DotNetCore
1515
{
1616
class ExampleRaw
1717
{
18-
public static void Run()
19-
{
20-
var lister = new LogixTagListing()
21-
{
22-
Gateway = "192.168.0.1",
23-
Path = "1,0",
24-
Timeout = TimeSpan.FromMilliseconds(1000),
25-
};
26-
27-
var tags = lister.ListTags();
28-
29-
foreach (var tag in tags)
30-
Console.WriteLine($"Id={tag.Id} Name={tag.Name} Type={tag.Type} Length={tag.Length}");
31-
}
3218

33-
class LogixTagListing
19+
public static void Run()
3420
{
35-
readonly Tag _rawCip = new Tag()
21+
// This payload is taken from https://github.com/libplctag/libplctag/blob/release/src/examples/test_raw_cip.c
22+
// but others can be found by analysing the Rockwell or other manufacturer's documentation
23+
// https://literature.rockwellautomation.com/idc/groups/literature/documents/pm/1756-pm020_-en-p.pdf pg 39
24+
25+
ReadOnlySpan<byte> raw_payload = [
26+
0x55,
27+
0x03,
28+
0x20, 0x6b, 0x25, 0x00, 0x00, 0x00,
29+
0x04, 0x00,
30+
0x02, 0x00,
31+
0x07, 0x00,
32+
0x08, 0x00,
33+
0x01, 0x00
34+
];
35+
36+
var cipService = new Tag()
3637
{
3738
PlcType = PlcType.ControlLogix,
3839
Protocol = Protocol.ab_eip,
40+
Gateway = "10.10.10.10",
41+
Path = "1,0",
3942
Name = "@raw",
4043
};
41-
42-
public string Gateway { get => _rawCip.Gateway; set => _rawCip.Gateway = value; }
43-
public string Path { get => _rawCip.Path; set => _rawCip.Path = value; }
44-
public TimeSpan Timeout { get => _rawCip.Timeout; set => _rawCip.Timeout = value; }
45-
46-
public List<TagInfo> ListTags()
47-
{
48-
// This payload is taken from https://github.com/libplctag/libplctag/blob/release/src/examples/test_raw_cip.c
49-
// but others can be found by analysing the Rockwell or other manufacturer's documentation
50-
// https://literature.rockwellautomation.com/idc/groups/literature/documents/pm/1756-pm020_-en-p.pdf pg 39
51-
52-
var raw_payload = new byte[] {
53-
0x55,
54-
0x03,
55-
0x20,
56-
0x6b,
57-
0x25,
58-
0x00,
59-
0x00,
60-
0x00,
61-
0x04,
62-
0x00,
63-
0x02,
64-
0x00,
65-
0x07,
66-
0x00,
67-
0x08,
68-
0x00,
69-
0x01,
70-
0x00
71-
};
72-
73-
_rawCip.Initialize();
74-
_rawCip.SetSize(raw_payload.Length);
75-
_rawCip.SetBuffer(raw_payload);
76-
_rawCip.Write();
77-
78-
var responseSize = _rawCip.GetSize();
79-
80-
var tagInfos = new List<TagInfo>();
81-
int offset = 0;
82-
while (offset < responseSize)
83-
tagInfos.Add(DecodeOneTagInfo(ref offset));
84-
85-
return tagInfos;
86-
}
87-
88-
public class TagInfo
89-
{
90-
public uint Id { get; set; }
91-
public ushort Type { get; set; }
92-
public string Name { get; set; }
93-
public ushort Length { get; set; }
94-
public uint[] Dimensions { get; set; }
95-
}
96-
97-
TagInfo DecodeOneTagInfo(ref int offset)
44+
cipService.Initialize();
45+
cipService.SetSize(raw_payload.Length);
46+
cipService.SetBuffer(raw_payload);
47+
cipService.Write();
48+
Span<byte> res = stackalloc byte[cipService.GetSize()];
49+
cipService.GetBuffer(res);
50+
51+
var tagInfos = new List<TagInfo>();
52+
for (int cursor = 0; cursor < res.Length;)
9853
{
99-
100-
var tagInstanceId = _rawCip.GetUInt32(offset);
101-
var tagType = _rawCip.GetUInt16(offset + 4);
102-
var tagLength = _rawCip.GetUInt16(offset + 6);
103-
var tagArrayDims = new uint[]
104-
{
105-
_rawCip.GetUInt32(offset + 8),
106-
_rawCip.GetUInt32(offset + 12),
107-
_rawCip.GetUInt32(offset + 16)
108-
};
109-
110-
var apparentTagNameLength = (int)_rawCip.GetUInt16(offset + 20);
111-
const int TAG_STRING_SIZE = 200;
112-
var actualTagNameLength = Math.Min(apparentTagNameLength, TAG_STRING_SIZE * 2 - 1);
113-
114-
var tagNameBytes = Enumerable.Range(offset + 22, actualTagNameLength)
115-
.Select(o => _rawCip.GetUInt8(o))
116-
.Select(Convert.ToByte)
117-
.ToArray();
118-
119-
var tagName = Encoding.ASCII.GetString(tagNameBytes);
120-
121-
offset = 22 + actualTagNameLength;
122-
123-
return new TagInfo()
124-
{
125-
Id = tagInstanceId,
126-
Type = tagType,
127-
Name = tagName,
128-
Length = tagLength,
129-
Dimensions = tagArrayDims
130-
};
131-
54+
var tagNameLength = U16(res, cursor + 20);
55+
tagInfos.Add(new (
56+
Id : U32(res, cursor + 0),
57+
Type : U16(res, cursor + 4),
58+
Length : U16(res, cursor + 6),
59+
Dimensions : [
60+
U32(res, cursor + 8),
61+
U32(res, cursor + 12),
62+
U32(res, cursor + 16)
63+
],
64+
Name : ASCII(res, cursor + 22, tagNameLength)
65+
));
66+
67+
cursor += 22 + tagNameLength;
13268
}
13369

70+
foreach (var tag in tagInfos)
71+
Console.WriteLine($"Id={tag.Id} Name={tag.Name} Type={tag.Type} Length={tag.Length}");
13472
}
13573

74+
record TagInfo(uint Id, ushort Type, ushort Length, uint[] Dimensions, string Name);
75+
static ushort U16(ReadOnlySpan<byte> bs, int offset) => BinaryPrimitives.ReadUInt16LittleEndian(bs[offset..]);
76+
static uint U32(ReadOnlySpan<byte> bs, int offset) => BinaryPrimitives.ReadUInt32LittleEndian(bs[offset..]);
77+
static string ASCII(ReadOnlySpan<byte> bs, int offset, int len) => Encoding.ASCII.GetString(bs[offset..(offset+len)]);
13678
}
13779

13880
}

src/libplctag.NativeImport/plctag.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,35 +281,36 @@ public static int plc_tag_get_string_total_length(Int32 tag_id, int string_start
281281

282282
public static int plc_tag_get_raw_bytes(Int32 tag_id, int start_offset, byte[] buffer, int buffer_length)
283283
{
284-
int returnValue = plc_tag_get_raw_bytes(tag_id, start_offset, out Span<byte> span);
284+
Span<byte> span = buffer.AsSpan().Slice(0, buffer_length);
285+
int returnValue = plc_tag_get_raw_bytes(tag_id, start_offset, span);
285286
span.CopyTo(buffer);
286287
return returnValue;
287288
}
288289

289-
public static int plc_tag_get_raw_bytes(Int32 tag_id, int start_offset, out Span<byte> buffer)
290+
public static int plc_tag_get_raw_bytes(Int32 tag_id, int start_offset, Span<byte> buffer)
290291
{
291292
unsafe
292293
{
293294
fixed (byte* ptr = buffer)
294295
{
295-
return NativeMethods.plc_tag_get_raw_bytes(tag_id, 0, ptr, buffer.Length);
296+
return NativeMethods.plc_tag_get_raw_bytes(tag_id, start_offset, ptr, buffer.Length);
296297
}
297298
}
298299
}
299300

300301
public static int plc_tag_set_raw_bytes(Int32 tag_id, int start_offset, byte[] buffer, int buffer_length)
301302
{
302-
ReadOnlySpan<byte> span = buffer.AsSpan().Slice(start_offset, buffer_length);
303-
return plc_tag_set_raw_bytes(tag_id, span);
303+
ReadOnlySpan<byte> span = buffer.AsSpan();
304+
return plc_tag_set_raw_bytes(tag_id, start_offset, span);
304305
}
305306

306-
public static int plc_tag_set_raw_bytes(Int32 tag_id, ReadOnlySpan<byte> buffer)
307+
public static int plc_tag_set_raw_bytes(Int32 tag_id, int start_offset, ReadOnlySpan<byte> buffer)
307308
{
308309
unsafe
309310
{
310311
fixed (byte* ptr = buffer)
311312
{
312-
return NativeMethods.plc_tag_set_raw_bytes(tag_id, 0, ptr, buffer.Length);
313+
return NativeMethods.plc_tag_set_raw_bytes(tag_id, start_offset, ptr, buffer.Length);
313314
}
314315
}
315316
}

src/libplctag/INative.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ interface INative
6363
int plc_tag_unregister_logger(int tag_id);
6464
int plc_tag_write(int tag, int timeout);
6565
int plc_tag_get_raw_bytes(int tag, int start_offset, byte[] buffer, int buffer_length);
66+
int plc_tag_get_raw_bytes(int tag, int start_offset, Span<byte> buffer);
6667
int plc_tag_set_raw_bytes(int tag, int start_offset, byte[] buffer, int buffer_length);
68+
int plc_tag_set_raw_bytes(int tag, int start_offset, ReadOnlySpan<byte> buffer);
6769
int plc_tag_get_string_length(int tag, int string_start_offset);
6870
int plc_tag_get_string(int tag, int string_start_offset, StringBuilder buffer, int buffer_length);
6971
int plc_tag_get_string_total_length(int tag, int string_start_offset);

src/libplctag/Native.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ class Native : INative
5959
public int plc_tag_set_bit(Int32 tag, int offset_bit, int val) => plctag.plc_tag_set_bit(tag, offset_bit, val);
6060
public void plc_tag_set_debug_level(int debug_level) => plctag.plc_tag_set_debug_level(debug_level);
6161
public int plc_tag_get_raw_bytes(int tag, int start_offset, byte[] buffer, int buffer_length) => plctag.plc_tag_get_raw_bytes(tag, start_offset, buffer, buffer_length);
62+
public int plc_tag_get_raw_bytes(int tag, int start_offset, Span<byte> buffer) => plctag.plc_tag_get_raw_bytes(tag, start_offset, buffer);
6263
public int plc_tag_set_raw_bytes(int tag, int start_offset, byte[] buffer, int buffer_length) => plctag.plc_tag_set_raw_bytes(tag, start_offset, buffer, buffer_length);
64+
public int plc_tag_set_raw_bytes(int tag, int start_offset, ReadOnlySpan<byte> buffer) => plctag.plc_tag_set_raw_bytes(tag, start_offset, buffer);
6365
public int plc_tag_get_string_length(int tag, int string_start_offset) => plctag.plc_tag_get_string_length(tag, string_start_offset);
6466
public int plc_tag_get_string(int tag, int string_start_offset, StringBuilder buffer, int buffer_length) => plctag.plc_tag_get_string(tag, string_start_offset, buffer, buffer_length);
6567
public int plc_tag_get_string_total_length(int tag, int string_start_offset) => plctag.plc_tag_get_string_total_length(tag, string_start_offset);

src/libplctag/Tag.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,30 @@ public void GetBuffer(int offset, byte[] buffer, int length)
948948
ThrowIfStatusNotOk(result);
949949
}
950950

951+
public void GetBuffer(Span<byte> buffer)
952+
{
953+
GetBuffer(0, buffer);
954+
}
955+
956+
public void GetBuffer(int offset, Span<byte> buffer)
957+
{
958+
ThrowIfAlreadyDisposed();
959+
var result = (Status)_native.plc_tag_get_raw_bytes(nativeTagHandle, offset, buffer);
960+
ThrowIfStatusNotOk(result);
961+
}
962+
963+
public void SetBuffer(ReadOnlySpan<byte> buffer)
964+
{
965+
SetBuffer(0, buffer);
966+
}
967+
968+
public void SetBuffer(int start_offset, ReadOnlySpan<byte> buffer)
969+
{
970+
ThrowIfAlreadyDisposed();
971+
var result = (Status)_native.plc_tag_set_raw_bytes(nativeTagHandle, start_offset, buffer);
972+
ThrowIfStatusNotOk(result);
973+
}
974+
951975
public void SetBuffer(byte[] buffer)
952976
{
953977
SetBuffer(0, buffer, buffer.Length);

src/libplctag/libplctag.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
</PropertyGroup>
3939

4040
<ItemGroup>
41-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
41+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
42+
<PackageReference Include="System.Memory" Version="4.6.0" />
43+
</ItemGroup>
4244
</ItemGroup>
4345

4446
</Project>

0 commit comments

Comments
 (0)