1 ///
2 module modbus.backend.specrules;
3 
4 version (modbus_verbose)
5     import std.experimental.logger;
6 
7 ///
8 interface SpecRules
9 {
10 pure:
11     ///
12     @property size_t deviceTypeSize();
13 
14     ///
15     const(void)[] packDF(ulong dev, ubyte fnc);
16     ///
17     void peekDF(const(void)[] buf, ref ulong dev, ref ubyte fnc);
18 
19     ///
20     const(void)[] pack(byte);
21     ///
22     const(void)[] pack(short);
23     ///
24     const(void)[] pack(int);
25     ///
26     const(void)[] pack(long);
27     ///
28     const(void)[] pack(float);
29     ///
30     const(void)[] pack(double);
31 }
32 
33 ///
34 class BasicSpecRules : SpecRules
35 {
36 protected:
37     ubyte[16] buffer;
38 
39 public:
40 
41 pure:
42 
43     override
44     {
45         @property size_t deviceTypeSize() { return 1; }
46 
47         const(void)[] packDF(ulong dev, ubyte fnc) 
48         {
49             import std.bitmanip : write;
50             assert(dev <= 255, "device number can't be more 255");
51             buffer[].write(cast(ubyte)dev, 0);
52             buffer[].write(fnc, 1);
53             return buffer[0..2];
54         }
55 
56         void peekDF(const(void)[] vbuf, ref ulong dev, ref ubyte fnc)
57         {
58             import std.bitmanip : peek;
59             auto buf = cast(const(ubyte)[])vbuf;
60             if (buf.length >= 1) dev = buf.peek!ubyte(0);
61             else version (modbus_verbose) debug
62                 .error("short readed message: can't read device number");
63             if (buf.length >= 2) fnc = buf.peek!ubyte(1);
64             else version (modbus_verbose) debug
65                 .error("short readed message: can't read function number");
66         }
67 
68         const(void)[] pack(byte v) { return tpack(v); }
69         const(void)[] pack(short v) { return tpack(v); }
70         const(void)[] pack(int v) { return tpack(v); }
71         const(void)[] pack(long v) { return tpack(v); }
72         const(void)[] pack(float v) { return tpack(v); }
73         const(void)[] pack(double v) { return tpack(v); }
74     }
75 
76 private:
77 
78     const(void)[] tpack(T)(T v)
79     {
80         import std.bitmanip : write;
81         buffer[].write(v, 0);
82         return buffer[0..T.sizeof];
83     }
84 }
85 
86 ///
87 class PilotBMSSpecRules : BasicSpecRules
88 {
89 public pure override:
90     @property size_t deviceTypeSize() { return 4; }
91 
92     const(void)[] packDF(ulong dev, ubyte fnc) 
93     {
94         import std.bitmanip : write;
95         size_t idx = 0;
96         buffer[].write(cast(ushort)(dev), &idx);
97         buffer[].write(cast(ushort)(dev>>16), &idx);
98         buffer[].write(fnc, &idx);
99         return buffer[0..idx];
100     }
101 
102     void peekDF(const(void)[] vbuf, ref ulong dev, ref ubyte fnc)
103     {
104         import std.bitmanip : peek;
105         size_t idx = 0;
106         auto buf = cast(const(ubyte)[])vbuf;
107         if (buf.length >= 4)
108         {
109             const a = buf.peek!ushort(&idx);
110             const b = buf.peek!ushort(&idx);
111             dev = (b << 16) | a;
112         }
113         else version (modbus_verbose) debug
114             .error("short readed message: can't read device number");
115         if (buf.length >= idx) fnc = buf.peek!ubyte(idx);
116         else version (modbus_verbose) debug
117             .error("short readed message: can't read function number");
118     }
119 }