1 ///
2 module modbus.backend.tcp;
3 
4 import modbus.backend.base;
5 
6 ///
7 class TCP : BaseBackend!260
8 {
9 protected:
10     // transaction id size + protocol id size + packet length size
11     enum packedServiceData = ushort.sizeof * 3;
12     enum packedLengthOffset = ushort.sizeof * 2;
13 public:
14     ///
15     this(Connection c, SpecRules s=null)
16     { super(c, s, packedServiceData, packedServiceData); }
17 
18 override:
19 
20     ///
21     void start(ulong dev, ubyte func)
22     {
23         short zero = 0;
24         // transaction id
25         append(zero);
26         // protocol id
27         append(zero);
28         // packet length (change in send)
29         append(zero);
30         appendDF(dev, func);
31     }
32 
33     ///
34     void send()
35     {
36         import std.bitmanip : nativeToBigEndian;
37         scope (exit) idx = 0;
38         auto dsize = cast(ushort)(idx - packedServiceData);
39         enum plo = packedLengthOffset;
40         buffer[plo..plo+ushort.sizeof] = nativeToBigEndian(dsize);
41         conn.write(buffer[0..idx]);
42 
43         version (modbus_verbose)
44             .trace("write bytes: ", buffer[0..idx]);
45     }
46 
47     ///
48     Response read(size_t expectedBytes)
49     {
50         import std.bitmanip : bigEndianToNative;
51 
52         auto res = baseRead(expectedBytes, true);
53         auto tmp = cast(ubyte[])res.data;
54 
55         auto plen = bigEndianToNative!ushort(cast(ubyte[2])tmp[4..6]);
56 
57         if (tmp.length != plen+packedServiceData)
58             throw readDataLengthException(res.dev, res.fnc,
59                             plen+packedServiceData, tmp.length);
60 
61         res.data = tmp[devOffset+sr.deviceTypeSize+functionTypeSize..$];
62 
63         return res;
64     }
65 }
66 
67 unittest
68 {
69     import std.array : appender;
70     auto buf = appender!(ubyte[]);
71     auto tcp = new TCP(new class Connection
72     {
73         override void write(const(void)[] data)
74         { buf.put(cast(const(ubyte)[])data); }
75         override void[] read(void[] buffer)
76         { return buffer[0..1]; }
77     });
78     tcp.start(1,2);
79     int xx = 123;
80     tcp.append(xx);
81     tcp.send();
82     assert (buf.data == [0,0, 0,0, 0,6, 1, 2, 0,0,0,123]);
83 }