1 /// 2 module modbus.protocol.base; 3 4 public import std.bitmanip : BitArray; 5 public import std.exception : enforce; 6 public import std.datetime.stopwatch; 7 public import std.conv : to; 8 9 version (modbus_verbose) 10 public import std.experimental.logger; 11 12 public import modbus.exception; 13 public import modbus.connection; 14 public import modbus.backend; 15 public import modbus.types; 16 public import modbus.func; 17 18 package enum MAX_BUFFER = 260; 19 20 /// 21 class Modbus 22 { 23 protected: 24 void[MAX_BUFFER] buffer; 25 26 Backend be; 27 28 void delegate(Duration) sleepFunc; 29 30 void sleep(Duration dur) 31 { 32 import core.thread; 33 34 if (sleepFunc !is null) sleepFunc(dur); 35 else 36 { 37 if (auto fiber = Fiber.getThis) 38 { 39 auto dt = StopWatch(AutoStart.yes); 40 while (dt.peek.to!Duration < dur) 41 fiber.yield(); 42 } 43 else Thread.sleep(dur); 44 } 45 } 46 47 /// 48 Duration writeStepPause() @property 49 { return (cast(ulong)(1e7 * 10 / 9600.0)).hnsecs; } 50 51 public: 52 53 /// 54 this(Backend be, void delegate(Duration) sf=null) 55 { 56 this.be = enforce(be, modbusException("backend is null")); 57 this.sleepFunc = sf; 58 } 59 60 /// 61 Backend backend() @property { return be; } 62 63 /// 64 Duration writeTimeout=10.msecs; 65 /// time for waiting message 66 Duration readTimeout=1.seconds; 67 68 /++ Write to serial port 69 70 Params: 71 dev = modbus device address (number) 72 fnc = function number 73 args = writed data in native endian 74 Returns: 75 sended message 76 +/ 77 const(void)[] write(Args...)(ulong dev, ubyte fnc, Args args) 78 { 79 auto buf = be.buildMessage(buffer, dev, fnc, args); 80 81 size_t cnt = be.connection.write(buf); 82 if (cnt == buf.length) return buf; 83 84 auto dt = StopWatch(AutoStart.yes); 85 while (cnt != buf.length) 86 { 87 cnt += be.connection.write(buf[cnt..$]); 88 this.sleep(writeStepPause); 89 if (dt.peek.to!Duration > writeTimeout) 90 throw modbusTimeoutException("write", dev, fnc, writeTimeout); 91 } 92 93 return buf; 94 } 95 96 /// 97 void setSleepFunc(void delegate(Duration) f) { sleepFunc = f; } 98 }