1 ///
2 module modbus.backend.tcp;
3 
4 import std.bitmanip;
5 
6 import modbus.backend.base;
7 
8 ///
9 class TCP : BaseBackend
10 {
11 protected:
12     // transaction id size + protocol id size + packet length size
13     enum packetServiceData = ushort.sizeof * 3;
14     enum packetLengthOffset = ushort.sizeof * 2;
15 public:
16     ///
17     this(SpecRules s=null)
18     { super(s, packetServiceData, packetServiceData); }
19 
20 protected override:
21     void startMessage(void[] buf, ref size_t idx, ulong dev, ubyte fnc, ulong stamp)
22     {
23         const ushort zero;
24         // transaction id
25         append(buf, idx, cast(ushort)stamp);
26         // protocol id
27         append(buf, idx, zero);
28         // packet length (change in finalizeMessage)
29         append(buf, idx, zero);
30         appendDF(buf, idx, dev, fnc);
31     }
32 
33     void finalizeMessage(void[] buf, ref size_t idx)
34     {
35         auto dsize = cast(ushort)(idx - packetServiceData);
36         size_t plo = packetLengthOffset;
37         append(buf, plo, dsize);
38     }
39 
40     bool check(const(void)[] data)
41     {
42         enum plo = packetLengthOffset;
43         auto lenbytes = cast(ubyte[2])data[plo..plo+ushort.sizeof];
44         auto len = bigEndianToNative!ushort(lenbytes);
45         return len == (data.length - packetServiceData);
46     }
47 
48     ulong getStamp(const(void)[] data)
49     { return bigEndianToNative!ushort((cast(ubyte[2])data[0..2])); }
50 
51     size_t endDataSplit() @property { return 0; }
52 }
53 
54 unittest
55 {
56     import std.array : appender;
57     void[100] data = void;
58     auto tcp = new TCP();
59     int xx = 123;
60     auto res = cast(ubyte[])tcp.buildMessage(data, 1, 2, 0, xx);
61     assert (res == [0,0, 0,0, 0,6, 1, 2, 0,123,0,0]);
62     assert (tcp.check(res));
63 }