1 /// 2 module modbus.exception; 3 4 import std.string : format; 5 import std.datetime : Duration; 6 7 enum MINIMUM_MODBUS_MSG_LENGTH = 5; 8 9 /// 10 class ModbusException : Exception 11 { 12 /// 13 this(string msg, string file=__FILE__, size_t line=__LINE__) 14 @nogc @safe pure nothrow 15 { super(msg, file, line); } 16 } 17 18 /// 19 class ModbusIOException : ModbusException 20 { 21 /// 22 ulong dev; 23 /// 24 ubyte fnc; 25 26 this(string msg, ulong dev, ubyte fnc, 27 string file=__FILE__, size_t line=__LINE__) 28 @nogc @safe pure nothrow 29 { 30 super(msg, file, line); 31 this.dev = dev; 32 this.fnc = fnc; 33 } 34 } 35 36 /// 37 class ModbusTimeoutException : ModbusIOException 38 { 39 /// 40 Duration dur; 41 /// 42 this(string msg, ulong dev, ubyte fnc, Duration dur, 43 string file=__FILE__, size_t line=__LINE__) 44 @nogc @safe pure nothrow 45 { 46 super(msg, dev, fnc, file, line); 47 this.dur = dur; 48 } 49 } 50 51 /// 52 class ModbusDevException : ModbusIOException 53 { 54 /// 55 private ubyte[256] writeBuffer; 56 /// 57 private size_t writeLength; 58 /// 59 private ubyte[256] readBuffer; 60 /// 61 private size_t readLength; 62 63 /// 64 this(ulong dev, ubyte fnc, string msg, 65 string file=__FILE__, size_t line=__LINE__) 66 { super(msg, dev, fnc, file, line); } 67 68 @property 69 { 70 void writed(const(void)[] b) 71 { 72 auto ln = b.length; 73 writeBuffer[0..ln] = cast(ubyte[])(b[0..ln]); 74 writeLength = ln; 75 } 76 77 const(void)[] writed() const 78 { return writeBuffer[0..writeLength]; } 79 80 void readed(const(void)[] b) 81 { 82 auto ln = b.length; 83 readBuffer[0..ln] = cast(ubyte[])(b[0..ln]); 84 readLength = ln; 85 } 86 87 const(void)[] readed() const 88 { return readBuffer[0..readLength]; } 89 } 90 } 91 92 /// 93 class CheckFailException : ModbusDevException 94 { 95 /// 96 this(ulong dev, ubyte fnc, 97 string file=__FILE__, size_t line=__LINE__) 98 { 99 super(dev, fnc, format("dev %d fnc %d(0x%x) recive msg CRC check fails", 100 dev, fnc, fnc), file, line); 101 } 102 } 103 104 /// 105 class FunctionErrorException : ModbusDevException 106 { 107 /// 108 ubyte res; 109 /// 110 FunctionErrorCode code; 111 112 /// 113 this(ulong dev, ubyte fnc, ubyte res, ubyte code, 114 string file=__FILE__, size_t line=__LINE__) 115 { 116 this.res = res; 117 this.code = cast(FunctionErrorCode)code; 118 119 super(dev, fnc, format("dev %d fnc %d(0x%x) recive fnc %d(0x%x) with "~ 120 "exception code %s (%d)", dev, fnc, fnc, res, res, 121 cast(FunctionErrorCode)code, code), file, line); 122 } 123 } 124 125 /// 126 class ReadDataLengthException : ModbusDevException 127 { 128 size_t expected, responseLength; 129 /// 130 this(ulong dev, ubyte fnc, size_t exp, size_t res, 131 string file=__FILE__, size_t line=__LINE__) 132 { 133 expected = exp; 134 responseLength = res; 135 super(dev, fnc, format("dev %d fnc to %d(0x%x) recieves wrong"~ 136 " count of bytes (%d != expected %d or more what %d)", 137 dev, fnc, fnc, res, exp, MINIMUM_MODBUS_MSG_LENGTH), file, line); 138 } 139 } 140 141 /// 142 enum FunctionErrorCode : ubyte 143 { 144 ILLEGAL_FUNCTION = 1, /// 1 145 ILLEGAL_DATA_ADDRESS = 2, /// 2 146 ILLEGAL_DATA_VALUE = 3, /// 3 147 SLAVE_DEVICE_FAILURE = 4, /// 4 148 ACKNOWLEDGE = 5, /// 5 149 SLAVE_DEVICE_BUSY = 6, /// 6 150 MEMORY_PARITY_ERROR = 8, /// 8 151 GATEWAY_PATH_UNAVAILABLE = 0xA, /// 0xA 152 GATEWAY_TARGET_DEVICE_FAILED_TO_RESPOND = 0xB, /// 0xB 153 } 154 155 private version (modbus_use_prealloc_exceptions) 156 { 157 __gshared 158 { 159 auto preallocModbusException = new ModbusException("many args"); 160 auto preallocModbusTimeoutException = new ModbusTimeoutException("many args", Duration.init); 161 auto preallocCheckFailException = new CheckFailException(0, 0); 162 auto preallocReadDataLengthException = new ReadDataLengthException(0,0,0,0); 163 auto preallocFunctionErrorException = new FunctionErrorException(0,0,0,0); 164 } 165 } 166 167 /// Returns: preallocated exception with new values of fields 168 ModbusException modbusException()(string msg, string file=__FILE__, size_t line=__LINE__) 169 { 170 version (modbus_use_prealloc_exceptions) 171 { 172 preallocModbusException.msg = msg; 173 preallocModbusException.file = file; 174 preallocModbusException.line = line; 175 return preallocModbusException; 176 } 177 else return new ModbusException(msg, file, line); 178 } 179 180 /// Returns: preallocated exception with new values of fields 181 ModbusTimeoutException modbusTimeoutException()(string msg, ulong dev, ubyte fnc, Duration dur, string file=__FILE__, size_t line=__LINE__) 182 { 183 version (modbus_use_prealloc_exceptions) 184 { 185 preallocModbusTimeoutException.msg = msg; 186 preallocModbusTimeoutException.dev = dev; 187 preallocModbusTimeoutException.fnc = fnc; 188 preallocModbusTimeoutException.dur = dur; 189 preallocModbusTimeoutException.file = file; 190 preallocModbusTimeoutException.line = line; 191 return preallocModbusTimeoutException; 192 } 193 else return new ModbusTimeoutException(msg, dev, fnc, dur, file, line); 194 } 195 196 /// Returns: preallocated exception with new values of fields 197 CheckFailException checkFailException()(ulong dev, ubyte fnc, 198 string file=__FILE__, size_t line=__LINE__) 199 { 200 version (modbus_use_prealloc_exceptions) 201 { 202 preallocCheckFailException.msg = "check CRC fails"; 203 preallocCheckFailException.dev = dev; 204 preallocCheckFailException.fnc = fnc; 205 preallocCheckFailException.file = file; 206 preallocCheckFailException.line = line; 207 return preallocCheckFailException; 208 } 209 else return new CheckFailException(dev, fnc, file, line); 210 } 211 212 /// Returns: preallocated exception with new values of fields 213 FunctionErrorException functionErrorException()(ulong dev, ubyte fnc, ubyte res, ubyte code, 214 string file=__FILE__, size_t line=__LINE__) 215 { 216 version (modbus_use_prealloc_exceptions) 217 { 218 preallocFunctionErrorException.msg = "error while read function response"; 219 preallocFunctionErrorException.dev = dev; 220 preallocFunctionErrorException.fnc = fnc; 221 preallocFunctionErrorException.res = res; 222 preallocFunctionErrorException.code = cast(FunctionErrorCode)code; 223 preallocFunctionErrorException.file = file; 224 preallocFunctionErrorException.line = line; 225 return preallocFunctionErrorException; 226 } 227 else return new FunctionErrorException(dev, fnc, res, code, file, line); 228 } 229 230 /// Returns: preallocated exception with new values of fields 231 ReadDataLengthException readDataLengthException()(ulong dev, ubyte fnc, size_t exp, size_t res, 232 string file=__FILE__, size_t line=__LINE__) 233 { 234 version (modbus_use_prealloc_exceptions) 235 { 236 preallocReadDataLengthException.msg = "error while read function response: wrong length"; 237 preallocReadDataLengthException.dev = dev; 238 preallocReadDataLengthException.fnc = fnc; 239 preallocReadDataLengthException.expected = exp; 240 preallocReadDataLengthException.responseLength = res; 241 preallocReadDataLengthException.file = file; 242 preallocReadDataLengthException.line = line; 243 return preallocReadDataLengthException; 244 } 245 else return new ReadDataLengthException(dev, fnc, exp, res, file, line); 246 }