1 module modbus.protocol.slave.device.simple; 2 3 import modbus.protocol.slave.device.base; 4 5 class SimpleModbusSlaveDevice : ModbusSlaveDevice 6 { 7 protected: 8 ulong _number; 9 ushort[0x7D] vals; 10 11 public: 12 13 this(ulong numb) { _number = numb; } 14 15 override 16 { 17 ulong number() @property { return _number; } 18 19 Response onMessage(ResponseWriter rw, ref const Message msg) 20 { 21 alias FC = FunctionCode; 22 23 auto st = cast(ushort[])msg.data[0..$/2*2]; 24 auto addr = rw.backend.unpackTT(st[0]); 25 auto voc = rw.backend.unpackTT(st[1]); 26 27 auto mltData() 28 { 29 auto umd = cast(ushort[])msg.data[5..$]; 30 foreach (i, v; umd) vals[i] = rw.backend.unpackTT(v); 31 return vals[0..umd.length]; 32 } 33 34 switch (msg.fnc) 35 { 36 case FC.readCoils: 37 return onReadCoils(rw, addr, voc); 38 case FC.readDiscreteInputs: 39 return onReadDiscreteInputs(rw, addr, voc); 40 case FC.readHoldingRegisters: 41 return onReadHoldingRegisters(rw, addr, voc); 42 case FC.readInputRegisters: 43 return onReadInputRegisters(rw, addr, voc); 44 case FC.writeSingleCoil: 45 return onWriteSingleCoil(rw, addr, voc); 46 case FC.writeSingleRegister: 47 return onWriteSingleRegister(rw, addr, voc); 48 case FC.writeMultipleCoils: 49 return onWriteMultipleCoils(rw, addr, mltData); 50 case FC.writeMultipleRegisters: 51 return onWriteMultipleRegisters(rw, addr, mltData); 52 default: 53 return onOtherFunction(rw, msg.fnc, msg.data); 54 } 55 } 56 } 57 58 Response onReadCoils(ResponseWriter rw, ushort addr, ushort count) 59 { return Response.illegalFunction; } 60 61 Response onReadDiscreteInputs(ResponseWriter rw, ushort addr, ushort count) 62 { return Response.illegalFunction; } 63 64 Response onReadHoldingRegisters(ResponseWriter rw, ushort addr, ushort count) 65 { return Response.illegalFunction; } 66 67 Response onReadInputRegisters(ResponseWriter rw, ushort addr, ushort count) 68 { return Response.illegalFunction; } 69 70 Response onWriteSingleCoil(ResponseWriter rw, ushort addr, ushort value) 71 { return Response.illegalFunction; } 72 73 Response onWriteSingleRegister(ResponseWriter rw, ushort addr, ushort value) 74 { return Response.illegalFunction; } 75 76 Response onWriteMultipleCoils(ResponseWriter rw, ushort addr, const(ushort)[] values) 77 { return Response.illegalFunction; } 78 79 Response onWriteMultipleRegisters(ResponseWriter rw, ushort addr, const(ushort)[] values) 80 { return Response.illegalFunction; } 81 82 Response onOtherFunction(ResponseWriter rw, ubyte func, const(void)[] data) 83 { return Response.illegalFunction; } 84 } 85 86 version (unittest): 87 88 class TestModbusSlaveDevice : SimpleModbusSlaveDevice 89 { 90 static struct Data 91 { 92 align(1): 93 uint value1; // 0 - 1 94 uint value2; // 2 - 3 95 char[16] str; // 4 - 11 96 float value3; // 12 - 13 97 ushort[12] usv; // 14 - 26 98 } 99 100 Data data; 101 102 this(ulong number) 103 { 104 super(number); 105 rndData(data); 106 } 107 108 void rndData(ref Data tdd) 109 { 110 import std.random : uniform; 111 112 tdd.value1 = uniform(0, uint.max); 113 tdd.value2 = uniform(0, uint.max); 114 tdd.str[] = cast(char)0; 115 tdd.str[0..5] = "hello"[]; 116 tdd.value3 = 3.1415; 117 foreach (ref v; tdd.usv) 118 v = uniform(ushort(0), ushort.max); 119 } 120 121 ushort[] buf() @property 122 { return cast(ushort[])((cast(void*)&data)[0..data.sizeof]); } 123 124 override: 125 126 Response onReadInputRegisters(ResponseWriter rw, ushort addr, ushort count) 127 { 128 if (count > 0x7D || count == 0) 129 return Response.illegalDataValue; 130 if (addr >= buf.length || addr+count > buf.length) 131 return Response.illegalDataAddress; 132 return rw.packArray(buf[addr..addr+count]); 133 } 134 135 Response onReadHoldingRegisters(ResponseWriter rw, ushort addr, ushort count) 136 { return onReadInputRegisters(rw, addr, count); } 137 138 Response onWriteSingleRegister(ResponseWriter rw, ushort addr, ushort value) 139 { 140 if (addr > buf.length) 141 return Response.illegalDataAddress; 142 buf[addr] = value; 143 return rw.pack(addr, value); 144 } 145 146 Response onWriteMultipleRegisters(ResponseWriter rw, ushort addr, const(ushort)[] values) 147 { 148 if (values.length > 0x7D || values.length == 0) 149 return Response.illegalDataValue; 150 if (addr >= buf.length || addr+values.length > buf.length) 151 return Response.illegalDataAddress; 152 buf[addr..addr+values.length] = values[]; 153 return rw.pack(addr, cast(ushort)values.length); 154 } 155 }