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 }