1 /// modbus with back end 2 module modbus.facade; 3 4 import modbus.backend; 5 import modbus.protocol; 6 7 version(Have_serialport) 8 { 9 public import std.datetime : Duration, dur, hnsecs, nsecs, msecs, seconds; 10 public import serialport; 11 12 /// Modbus with RTU backend constructs from existing serial port object 13 class ModbusRTU : Modbus 14 { 15 protected: 16 SerialPort _com; 17 18 class C : Connection 19 { 20 override: 21 void write(const(void)[] msg) 22 { _com.write(msg, writeTimeout); } 23 24 void[] read(void[] buffer) 25 { return _com.read(buffer, readTimeout, readFrameGap); } 26 } 27 28 public: 29 30 /// 31 Duration writeTimeout = 100.msecs, 32 readTimeout = 1.seconds, 33 readFrameGap = 4.msecs; 34 35 /// 36 this(SerialPort sp, SpecRules sr=null) 37 { 38 import std.exception : enforce; 39 _com = enforce(sp, "serial port is null"); 40 super(new RTU(new C, sr)); 41 } 42 43 @property 44 { 45 /// 46 SerialPort com() { return _com; } 47 /// 48 const(SerialPort) com() const { return _com; } 49 } 50 51 ~this() { _com.destroy(); } 52 } 53 } 54 55 import std.socket; 56 public import std.socket : Address, InternetAddress, Internet6Address; 57 version (Posix) public import std.socket : UnixAddress; 58 59 /// Modbus with TCP backend based on TcpSocket from std.socket 60 class ModbusTCP : Modbus 61 { 62 protected: 63 TcpSocket _socket; 64 65 void delegate() yieldFunc; 66 private void yield() { if (yieldFunc !is null) yieldFunc(); } 67 68 class C : Connection 69 { 70 override: 71 void write(const(void)[] msg) 72 { 73 size_t sent; 74 75 while (sent != msg.length) 76 { 77 const res = _socket.send(msg[sent..$]); 78 if (res == Socket.ERROR) 79 throw modbusException("error while send data to tcp socket"); 80 81 sent += res; 82 yield(); 83 } 84 } 85 86 void[] read(void[] buffer) 87 { 88 size_t received; 89 ptrdiff_t res = -1; 90 while (res != 0) 91 { 92 res = _socket.receive(buffer[received..$]); 93 if (res == Socket.ERROR) 94 throw modbusException("error while receive data from tcp socket"); 95 96 received += res; 97 yield(); 98 } 99 100 return buffer[0..received]; 101 } 102 } 103 104 public: 105 106 /// 107 this(Address addr, void delegate() yieldFunc=null, SpecRules sr=null) 108 { 109 _socket = new TcpSocket(addr); 110 111 if (yieldFunc !is null) 112 { 113 _socket.blocking(false); 114 this.yieldFunc = yieldFunc; 115 } 116 117 super(new TCP(new C, sr)); 118 } 119 120 @property 121 { 122 /// 123 TcpSocket socket() { return _socket; } 124 /// 125 const(TcpSocket) socket() const { return _socket; } 126 } 127 128 ~this() { _socket.close(); } 129 }